বাতিলকরণ টোকেন সম্পত্তি কীভাবে ব্যবহার করবেন?


117

শ্রেণি রুলিক্যান্সেলারের পূর্ববর্তী কোডের সাথে তুলনা করে , আমি কোডটি ব্যবহার করে চালাতে চেয়েছিলাম CancellationTokenSource

বাতিল টোকেন্সে উল্লিখিত হিসাবে আমি কীভাবে এটি ব্যবহার করব , অর্থাত্ কোনও ব্যতিক্রম ছোঁড়া / ধরা না দিয়ে? আমি কি IsCancellationRequestedসম্পত্তি ব্যবহার করতে পারি ?

আমি এটিকে এভাবে ব্যবহার করার চেষ্টা করেছি:

cancelToken.ThrowIfCancellationRequested();

এবং

try
{
  new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
  Console.WriteLine("Canceled!");
}

তবে এটি cancelToken.ThrowIfCancellationRequested();পদ্ধতিতে একটি রান-টাইম ত্রুটি দিয়েছে Work(CancellationToken cancelToken):

System.OperationCanceledException was unhandled
  Message=The operation was canceled.
  Source=mscorlib
  StackTrace:
       at System.Threading.CancellationToken.ThrowIfCancellationRequested()
       at _7CancellationTokens.Token.Work(CancellationToken cancelToken) in C:\xxx\Token.cs:line 33
       at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:\xxx\Token.cs:line 22
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

আমি যে কোডটি সাফল্যের সাথে চালিয়েছি তা নতুন থ্রেডে অপারেশন-ক্যান্সেলড এক্সসেপশনটি ধরেছে:

using System;
using System.Threading;
namespace _7CancellationTokens
{
  internal class Token
  {
    private static void Main()
    {
      var cancelSource = new CancellationTokenSource();
      new Thread(() =>
      {
         try
         {
           Work(cancelSource.Token); //).Start();
         }
         catch (OperationCanceledException)
         {
            Console.WriteLine("Canceled!");
         }
         }).Start();

      Thread.Sleep(1000);
      cancelSource.Cancel(); // Safely cancel worker.
      Console.ReadLine();
    }
    private static void Work(CancellationToken cancelToken)
    {
      while (true)
      {
        Console.Write("345");
        cancelToken.ThrowIfCancellationRequested();
      }
    }
  }
}

2
ডকস.মাইক্রোসফট.ইন- ইউএস / ডটনেট / স্ট্যান্ডার্ড / থ্রেডিং / এর অ্যাসিঙ্কCancellationTokenSource পদ্ধতিগুলি, পোলিংয়ের সাথে দীর্ঘকাল চলমান পদ্ধতিগুলি এবং কলব্যাক ব্যবহারের কয়েকটি দুর্দান্ত উদাহরণ রয়েছে ।
এহতেশ চৌধুরী

এই নিবন্ধগুলি আপনার কাছে থাকা বিকল্পগুলি দেখায় এবং আপনার নির্দিষ্ট কেস অনুসারে টোকেনটি পরিচালনা করতে হবে।
অগ্নিয়ান দিমিত্রভ

উত্তর:


140

আপনি নীচের হিসাবে আপনার কাজের পদ্ধতি বাস্তবায়ন করতে পারেন:

private static void Work(CancellationToken cancelToken)
{
    while (true)
    {
        if(cancelToken.IsCancellationRequested)
        {
            return;
        }
        Console.Write("345");
    }
}

এটাই. আপনাকে সর্বদা নিজের দ্বারা বাতিলকরণ পরিচালনা করতে হবে - প্রস্থান করার উপযুক্ত সময় হলে পদ্ধতি থেকে প্রস্থান করুন (যাতে আপনার কাজ এবং ডেটা ধারাবাহিক অবস্থায় থাকে)

আপডেট: আমি লিখতে পছন্দ করি না while (!cancelToken.IsCancellationRequested)কারণ প্রায়শই এমন খুব কম প্রস্থান পয়েন্ট থাকে যেখানে আপনি লুপ বডি জুড়ে নিরাপদে চালানো বন্ধ করতে পারেন এবং লুপের প্রস্থান করার জন্য কিছুটা যৌক্তিক শর্ত থাকে (সংগ্রহের সমস্ত আইটেমের উপর পুনরাবৃত্তি ইত্যাদি)। সুতরাং আমি বিশ্বাস করি যে শর্তগুলির মিশ্রণ না করাই ভাল they

এড়ানো সম্পর্কে সতর্কতা নোট CancellationToken.ThrowIfCancellationRequested():

ইমন নের্বোন কর্তৃক প্রশ্নের জবাবে মন্তব্য :

... এই উত্তর যেমনটি বলেছে ততক্ষণে ThrowIfCancellationRequestedএকগুচ্ছ চেকের পরিবর্তে গ্রেপ্তার IsCancellationRequested। তবে এটি কেবল একটি বাস্তবায়ন বিশদ নয়; যে পর্যবেক্ষণযোগ্য আচরণ প্রভাবিত: কাজের আর শেষ হয়ে যাবে বাতিল অবস্থায়, কিন্তু RanToCompletion। এবং এটি কেবল সুস্পষ্ট রাষ্ট্রের চেকগুলিকেই প্রভাবিত করতে পারে না ContinueWith, ব্যবহারের উপর নির্ভর করে আরও সূক্ষ্মভাবে, টাস্ক শৃঙ্খলাবদ্ধ করে TaskContinuationOptions। আমি বলব যে এড়ানো এড়ানো ThrowIfCancellationRequestedবিপজ্জনক পরামর্শ।


1
ধন্যবাদ! এটি অনলাইন লেখাগুলি থেকে অনুসরণ করে না, বেশ প্রামাণ্য (বইটি "সংক্ষেপে C # 4.0"?) আমি উদ্ধৃত করেছি। আপনি কি আমাকে "সর্বদা" সম্পর্কে একটি রেফারেন্স দিতে পারেন?
ফুলপ্রুফ

1
এটি অনুশীলন এবং অভিজ্ঞতা থেকে আসে =)। আমি এটা কোথা থেকে জানি তা মনে করতে পারছি না। আমি "আপনার সর্বদা প্রয়োজন" ব্যবহার করেছি কারণ আপনি থ্রেড.অবার্ট () ব্যবহার করে বাইরে থেকে ব্যতীত কর্মী থ্রেডকে বাধা দিতে পারেন, তবে এটি একটি খুব খারাপ অভ্যাস। যাইহোক, বাতিলকরণ টোকেন ব্যবহার করুন h থ্রোআইফক্যান্সেলেশন রিলেকুইস্টেড () এছাড়াও এটি করার অন্য উপায়, "নিজের দ্বারা বাতিলকরণ পরিচালনা করুন"।
সাশা

1
@ ওলেকসান্ডারপিশিনিচনি আমার অর্থ যখন (সত্য) তখন কিছুটা (! বাতিল টোকেন.আইএসসিলেসিলেশন রিসার্চড) এর সাথে প্রতিস্থাপন করেছেন। এটি সহায়ক ছিল! ধন্যবাদ!
ডগ ডসন

1
@ ফুলপ্রুফ রানটাইমটির জন্য চলমান কোড বাতিল করার কোনও জেনেরিক উপায় নেই কারণ রানটাইমগুলি যথেষ্ট স্মার্ট নয় যেখানে কোনও প্রক্রিয়াটি বাধাগ্রস্থ হতে পারে তা জানার পক্ষে নেই। কিছু ক্ষেত্রে কেবল একটি লুপ থেকে বেরিয়ে আসা সম্ভব হয়, অন্য ক্ষেত্রে আরও জটিল যুক্তি প্রয়োজন, অর্থাত্ লেনদেনকে ফিরিয়ে আনতে হবে, সংস্থানগুলি ছেড়ে দিতে হবে (যেমন ফাইল হ্যান্ডলগুলি বা নেটওয়ার্ক সংযোগ)। এ কারণেই কোনও কোড না লিখে কোনও কাজ বাতিল করার কোনও মায়াবী উপায় নেই। আপনি যা ভাবেন সেটি কোনও প্রক্রিয়া হত্যার মতো তবে এটি বাতিল হয় না যে কোনও অ্যাপ্লিকেশনটির মধ্যে সবচেয়ে খারাপ ঘটনা ঘটতে পারে কারণ পরিষ্কার করা যায় না।
ব্যবহারকারী 3285954

1
@ কোসিস্ট আপনি ক্যান্সেলেশন টোকেন ব্যবহার করতে পারেন you আপনি যদি নিজে নিজেই শুরু করা অপারেশনটি বাতিল করার পরিকল্পনা না করেন তবে কোনও। অবশ্যই যখন সিস্টেম প্রক্রিয়াটি হত্যা করা হয়, তখন সমস্ত কিছু বাধাগ্রস্ত হয় এবং বাতিলকরণ টোকেনের এর সাথে কোনও সম্পর্ক নেই। সুতরাং হ্যাঁ, আপনার যদি ক্রিয়াকলাপ বাতিল করতে সত্যিই এটির প্রয়োজন হয় তবে আপনার কেবল বাতিলকরণ টোকেনসোর্স তৈরি করা উচিত। আপনি ব্যবহার করবেন না এমন কিছু তৈরি করার কোনও ধারণা নেই।
সাশা

26

@ BrainSlugs83

স্ট্যাকওভারফ্লোতে পোস্ট করা সমস্ত কিছুকে আপনি অন্ধভাবে বিশ্বাস করবেন না। জেনস কোডে থাকা মন্তব্যটি ভুল, প্যারামিটার ব্যতিক্রম ছুঁড়ে ফেলেছে কিনা তা নিয়ন্ত্রণ করে না।

এমএসডিএন খুব পরিষ্কার যে সেই পরামিতিটি কী নিয়ন্ত্রণ করে, আপনি এটি পড়েছেন? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx

যদি throwOnFirstExceptionসত্য হয়, একটি ব্যতিক্রম তাত্ক্ষণিকভাবে বাতিল কলের বাইরে প্রচার করবে, অবশিষ্ট কলব্যাকগুলি এবং বাতিলকরণযোগ্য ক্রিয়াকলাপগুলি প্রক্রিয়াজাতকরণ থেকে বিরত করবে। যদি throwOnFirstExceptionএটি মিথ্যা হয় তবে এই ওভারলোডটি কোনও ব্যতিক্রমকে একত্রিত করবে AggregateException, যেমন একটি কলব্যাক ব্যতিক্রম ছুঁড়ে দেওয়া অন্য রেজিস্টার্ড কলব্যাকগুলি কার্যকর হতে বাধা দেয় না।

ভেরিয়েবলের নামটিও ভুল কারণ বাতিলকে ডাকা হয় CancellationTokenSourceনিজেই টোকেন নয় এবং উত্সটি প্রতিটি টোকেনের পরিচালনা করে এটির পরিচালনা করে।


বাতিলকরণ টোকেনের প্রস্তাবিত ব্যবহার সম্পর্কেও এখানে ডকুমেন্টেশন (টিএপি) দেখুন: ডকস.মাইক্রোসফটকম
en-

1
এটি খুব দরকারী তথ্য, তবে এটি মোটেই জিজ্ঞাসিত প্রশ্নের উত্তর দেয় না।
11nallan11

16

আপনি বাতিল টোকেন সহ একটি টাস্ক তৈরি করতে পারেন, যখন আপনি গোটো ব্যাকগ্রাউন্ড অ্যাপ করেন আপনি এই টোকেনটি বাতিল করতে পারেন।

আপনি এটি পিসিএল https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle এ করতে পারেন

var cancelToken = new CancellationTokenSource();
Task.Factory.StartNew(async () => {
    await Task.Delay(10000);
    // call web API
}, cancelToken.Token);

//this stops the Task:
cancelToken.Cancel(false);

এ্যাথার সলিউশনটি জামারিনে ব্যবহারকারী টাইমার For ফর্মগুলি, অ্যাপ্লিকেশনটির গোটো ব্যাকগ্রাউন্ড https://xamarinhelp.com/xamarin-forms-timer/ এ টাইমার বন্ধ করুন


10

আপনি ব্যবহার করতে পারেনThrowIfCancellationRequested ব্যতিক্রম পরিচালনা !

এর ব্যবহার ThrowIfCancellationRequestedবোঝানো হয়েছে একটি Task(ক Thread) এর মধ্যে থেকে ব্যবহার করা উচিত নয় । যখন একটি এর মধ্যে ব্যবহার করা হয় Task, আপনাকে নিজেই ব্যতিক্রমটি পরিচালনা করতে হবে না (এবং আনহ্যান্ডেল ব্যতিক্রমী ত্রুটিটি পান)। এটি ফলাফল ছেড়ে যাবে Task, এবংTask.IsCancelled সম্পত্তিটি সত্য হবে। কোনও ব্যতিক্রম হ্যান্ডলিংয়ের প্রয়োজন নেই।

আপনার নির্দিষ্ট ক্ষেত্রে, পরিবর্তন Threadএকটি থেকে Task

Task t = null;
try
{
    t = Task.Run(() => Work(cancelSource.Token), cancelSource.Token);
}

if (t.IsCancelled)
{
    Console.WriteLine("Canceled!");
}

আপনি কেন ব্যবহার করছেন t.Start()এবং করছেন না Task.Run()?
এক্সান্দার লুসিয়ানো

1
@ এক্সান্দারলুসিয়ানো: এই উদাহরণে কোনও নির্দিষ্ট কারণ নেই এবং টাস্ক.রুন () আরও ভাল পছন্দ হতে পারত।
টাইটাস

5

আপনাকে টাস্কটি পাস করতে CancellationTokenহবে, যা বাতিল হওয়ার অনুরোধ করা হয়েছে কিনা তা পর্যায়ক্রমে টোকেনটি পর্যবেক্ষণ করবে।

CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;  
Task task = Task.Run(() => {     
  while(!token.IsCancellationRequested) {
      Console.Write("*");         
      Thread.Sleep(1000);
  }
}, token);
Console.WriteLine("Press enter to stop the task"); 
Console.ReadLine(); 
cancellationTokenSource.Cancel(); 

এই ক্ষেত্রে, বাতিলকরণের অনুরোধ করা হলে অপারেশনটি শেষ হবে এবং এর Taskএকটি RanToCompletionরাষ্ট্র থাকবে। আপনি যদি স্বীকার করতে চান যে আপনার কাজটি বাতিল হয়ে গেছে , আপনাকে ThrowIfCancellationRequestedএকটি OperationCanceledExceptionব্যতিক্রম ছোঁড়াতে হবে।

Task task = Task.Run(() =>             
{                 
    while (!token.IsCancellationRequested) {
         Console.Write("*");                      
        Thread.Sleep(1000);                 
    }           
    token.ThrowIfCancellationRequested();               
}, token)
.ContinueWith(t =>
 {
      t.Exception?.Handle(e => true);
      Console.WriteLine("You have canceled the task");
 },TaskContinuationOptions.OnlyOnCanceled);  

Console.WriteLine("Press enter to stop the task");                 
Console.ReadLine();                 
cancellationTokenSource.Cancel();                 
task.Wait(); 

আশা করি এটি আরও ভালভাবে বুঝতে সহায়তা করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.