একটি থ্রেডে, আমি কিছু তৈরি করে System.Threading.Task
প্রতিটি কাজ শুরু করি ।
আমি যখন .Abort()
থ্রেডটি মেরে ফেলতে পারি , তখন কার্যগুলি বাতিল করা হয় না।
আমি কীভাবে .Abort()
আমার কাজগুলিতে প্রেরণ করতে পারি ?
একটি থ্রেডে, আমি কিছু তৈরি করে System.Threading.Task
প্রতিটি কাজ শুরু করি ।
আমি যখন .Abort()
থ্রেডটি মেরে ফেলতে পারি , তখন কার্যগুলি বাতিল করা হয় না।
আমি কীভাবে .Abort()
আমার কাজগুলিতে প্রেরণ করতে পারি ?
উত্তর:
আপনি পারবেন না। টাস্কগুলি থ্রেড পুল থেকে পটভূমি থ্রেড ব্যবহার করে। অ্যাওর্ট পদ্ধতি ব্যবহার করে থ্রেড বাতিল করারও প্রস্তাব দেওয়া হয় না। আপনি নিম্নলিখিত ব্লগ পোস্টটি একবার দেখে নিতে পারেন যা বাতিলকরণ টোকেনগুলি ব্যবহার করে কার্য বাতিল করার উপযুক্ত পদ্ধতি সম্পর্কে ব্যাখ্যা করে। এখানে একটি উদাহরণ:
class Program
{
static void Main()
{
var ts = new CancellationTokenSource();
CancellationToken ct = ts.Token;
Task.Factory.StartNew(() =>
{
while (true)
{
// do some heavy work here
Thread.Sleep(100);
if (ct.IsCancellationRequested)
{
// another thread decided to cancel
Console.WriteLine("task canceled");
break;
}
}
}, ct);
// Simulate waiting 3s for the task to complete
Thread.Sleep(3000);
// Can't wait anymore => cancel this task
ts.Cancel();
Console.ReadLine();
}
}
Task.Wait(TimeSpan / int)
এটি বাইরে থেকে একটি (সময় ভিত্তিক) সময়সীমা দেওয়ার জন্য ব্যবহার করা।
Task
পারি? ভালো কিছু: public int StartNewTask(Action method)
। ইনসাইড StartNewTask
পদ্ধতি আমি একটি নতুন তৈরি Task
করুন: Task task = new Task(() => method()); task.Start();
। সুতরাং আমি কিভাবে পরিচালনা করতে পারি CancellationToken
? আমিও মতো যদি জানেন যে হবে Thread
আমি যদি সেখানে কিছু কাজ এখনও Hangout এ আছেন করছি পরীক্ষা করার যুক্তিবিজ্ঞান বাস্তবায়ন এবং তাই যখন তাদের হত্যা প্রয়োজন Form.Closing
। সঙ্গে Threads
আমি ব্যবহার Thread.Abort()
।
আপনি যে থ্রেডটিতে টাস্কটি চলছে সেটিকে ক্যাপচার করা হলে কোনও টাস্ক আউট করা সহজেই সম্ভব this এটি প্রদর্শনের জন্য এখানে একটি উদাহরণ কোড দেওয়া হয়েছে:
void Main()
{
Thread thread = null;
Task t = Task.Run(() =>
{
//Capture the thread
thread = Thread.CurrentThread;
//Simulate work (usually from 3rd party code)
Thread.Sleep(1000);
//If you comment out thread.Abort(), then this will be displayed
Console.WriteLine("Task finished!");
});
//This is needed in the example to avoid thread being still NULL
Thread.Sleep(10);
//Cancel the task by aborting the thread
thread.Abort();
}
আমি এর জন্য সর্বাধিক সাধারণ ব্যবহারের কেসটি দেখানোর জন্য টাস্ক.আরুন () ব্যবহার করেছি - পুরানো একক থ্রেডযুক্ত কোড সহ টাস্কের সান্ত্বনা ব্যবহার করে, যা বাতিল করা উচিত কিনা তা নির্ধারণের জন্য বাতিলকরণ টোকেনসোর্স শ্রেণি ব্যবহার করে না।
CancellationToken
সমর্থন নেই ...
CancellationToken
বা এমনকি সহজ সমাধান যা জাতি-শর্ত মুক্ত বিনামূল্যে বিবেচনা করা উচিত। উপরের কোডটি কেবল ব্যবহারের ক্ষেত্র নয়, পদ্ধতিটি চিত্রিত করে।
thread
স্থানীয় ভেরিয়েবলের কাছে দেওয়া হবে)। আপনার কোডে আপনি তখন মূল থ্রেডটি বাতিল করতে পারেন যা আপনি আসলে যা চান তা নয়। অ্যাওর্টের আগে থ্রেডগুলি সমান হয় কিনা তা যদি আপনি পরীক্ষা বন্ধ করার জন্য জেদ করেন তবে একটি পরীক্ষা করা উচিত
ভালো লেগেছে এই পোস্ট প্রস্তাব দেওয়া, এই নিম্নলিখিত পদ্ধতিতে করা সম্ভব:
int Foo(CancellationToken token)
{
Thread t = Thread.CurrentThread;
using (token.Register(t.Abort))
{
// compute-bound work here
}
}
যদিও এটি কাজ করে, এ জাতীয় পদ্ধতির ব্যবহার করার পরামর্শ দেওয়া হয় না। যদি আপনি কার্য সম্পাদন করে এমন কোডটি নিয়ন্ত্রণ করতে পারেন তবে আপনি বাতিল করার সঠিক পরিচালনা সহ আরও ভাল d
এই ধরণের জিনিস হ্রাস করা হয় কেন Abort
একটি যৌক্তিক কারণ । প্রথম এবং সর্বাগ্রে, যদি সম্ভব হয় তবে কোনও থ্রেড বাতিল বা বন্ধ করতে ব্যবহার করবেন না Thread.Abort()
। Abort()
সময় মতো ফ্যাশনে থামার জন্য আরও শান্তিপূর্ণ অনুরোধগুলির প্রতিক্রিয়া না করে এমন এক থ্রেডকে জোরতার সাথে হত্যা করতে ব্যবহার করা উচিত।
বলা হচ্ছে, আপনাকে একটি ভাগ করা বাতিল সূচক সরবরাহ করতে হবে যা একটি থ্রেড সেট করে এবং অপেক্ষায় থাকে যখন অন্য থ্রেডটি পর্যায়ক্রমে পরীক্ষা করে এবং সানন্দে বের হয়। .NET 4, একটি কাঠামো এই কাজের জন্য বিশেষভাবে ডিজাইন করা রয়েছে CancellationToken
।
আপনার সরাসরি এটি করার চেষ্টা করা উচিত নয়। বাতিলকরণ টোকেনের সাথে কাজ করার জন্য আপনার কার্যগুলি ডিজাইন করুন এবং এগুলি এটিকে বাতিল করুন।
তদতিরিক্ত, আমি আপনার মূল থ্রেডটিও বাতিলকরণ টোকেনের মাধ্যমে ফাংশনে পরিবর্তনের পরামর্শ দেব। কল Thread.Abort()
করা একটি খারাপ ধারণা - এটি বিভিন্ন সমস্যার সমাধান করতে পারে যা নির্ণয় করা খুব কঠিন। পরিবর্তে, এই থ্রেডটি আপনার কাজগুলি ব্যবহার করে এমন একই বাতিলকরণ ব্যবহার CancellationTokenSource
করতে পারে - এবং একইটি আপনার সমস্ত কার্য এবং আপনার মূল থ্রেড বাতিল করতে ট্রিগার করতে ব্যবহার করা যেতে পারে ।
এটি অনেক সহজ এবং নিরাপদ, নকশার দিকে নিয়ে যাবে।
টাস্ক.ফ্যাক্টরি.স্টার্টনিউ () তে বেনামে পদ্ধতি ব্যবহার না করে বাতিলকরণ টোকেন কীভাবে ব্যবহার করবেন সে সম্পর্কে প্রেরাক কে-র প্রশ্নের উত্তর দিতে, আপনি এমএসডিএন উদাহরণে দেখানো হিসাবে স্টার্টনিউ () দিয়ে যে পদ্ধতিটি শুরু করছেন তাতে প্যারামিটার হিসাবে বাতিলকরণ টোকেনকে পাস করেন এখানে ।
যেমন
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
Task.Factory.StartNew( () => DoSomeWork(1, token), token);
static void DoSomeWork(int taskNum, CancellationToken ct)
{
// Do work here, checking and acting on ct.IsCancellationRequested where applicable,
}
আমি কোনও কাজ বাতিল করতে একটি মিশ্র পদ্ধতির ব্যবহার করি।
নীচে একটি উদাহরণ চেকআউট করুন:
private CancellationTokenSource taskToken;
private AutoResetEvent awaitReplyOnRequestEvent = new AutoResetEvent(false);
void Main()
{
// Start a task which is doing nothing but sleeps 1s
LaunchTaskAsync();
Thread.Sleep(100);
// Stop the task
StopTask();
}
/// <summary>
/// Launch task in a new thread
/// </summary>
void LaunchTaskAsync()
{
taskToken = new CancellationTokenSource();
Task.Factory.StartNew(() =>
{
try
{ //Capture the thread
runningTaskThread = Thread.CurrentThread;
// Run the task
if (taskToken.IsCancellationRequested || !awaitReplyOnRequestEvent.WaitOne(10000))
return;
Console.WriteLine("Task finished!");
}
catch (Exception exc)
{
// Handle exception
}
}, taskToken.Token);
}
/// <summary>
/// Stop running task
/// </summary>
void StopTask()
{
// Attempt to cancel the task politely
if (taskToken != null)
{
if (taskToken.IsCancellationRequested)
return;
else
taskToken.Cancel();
}
// Notify a waiting thread that an event has occurred
if (awaitReplyOnRequestEvent != null)
awaitReplyOnRequestEvent.Set();
// If 1 sec later the task is still running, kill it cruelly
if (runningTaskThread != null)
{
try
{
runningTaskThread.Join(TimeSpan.FromSeconds(1));
}
catch (Exception ex)
{
runningTaskThread.Abort();
}
}
}
CancellationToken
কাজটি বাতিল হয়ে যায় কিনা তা নিয়ন্ত্রণ করতে আপনি একটি ব্যবহার করতে পারেন । আপনি কি এটি শুরুর আগে ("কোনও বিষয় নয়, আমি ইতিমধ্যে এটি করেছি") বন্ধ করার বিষয়ে কথা বলছি না, বা আসলে এটি মাঝখানে বাধা দিচ্ছি? যদি প্রাক্তন হয় CancellationToken
তবে সাহায্যকারী হতে পারে; যদি দ্বিতীয়টি হয় তবে আপনাকে সম্ভবত আপনার নিজের "জামিন আউট" প্রক্রিয়াটি প্রয়োগ করতে হবে এবং আপনার দ্রুত ব্যর্থ হওয়া উচিত কিনা তা টাস্ক কার্যকর করার উপযুক্ত পয়েন্টগুলি পরীক্ষা করতে হবে (আপনি এখনও সাহায্যের জন্য বাতিলকরণ টোকেন ব্যবহার করতে পারেন তবে এটি কিছুটা বেশি ম্যানুয়াল)।
এমএসডিএন এর কার্যগুলি বাতিল করার বিষয়ে একটি নিবন্ধ রয়েছে: http://msdn.microsoft.com/en-us/library/dd997396.aspx
থ্রেডপুলে টাস্ক কার্যকর করা হচ্ছে (কমপক্ষে, যদি আপনি ডিফল্ট কারখানাটি ব্যবহার করে থাকেন), সুতরাং থ্রেডটি বাতিল করা কার্যগুলিকে প্রভাবিত করতে পারে না। বিসর্জন কার্যগুলির জন্য, এমএসডিএন-তে টাস্ক বাতিলকরণ দেখুন ।
আমি চেষ্টা করেছি CancellationTokenSource
কিন্তু আমি এটি করতে পারি না। এবং আমি আমার নিজস্ব উপায়ে এটি করেছি। এবং এটি কাজ করে।
namespace Blokick.Provider
{
public class SignalRConnectProvider
{
public SignalRConnectProvider()
{
}
public bool IsStopRequested { get; set; } = false; //1-)This is important and default `false`.
public async Task<string> ConnectTab()
{
string messageText = "";
for (int count = 1; count < 20; count++)
{
if (count == 1)
{
//Do stuff.
}
try
{
//Do stuff.
}
catch (Exception ex)
{
//Do stuff.
}
if (IsStopRequested) //3-)This is important. The control of the task stopping request. Must be true and in inside.
{
return messageText = "Task stopped."; //4-) And so return and exit the code and task.
}
if (Connected)
{
//Do stuff.
}
if (count == 19)
{
//Do stuff.
}
}
return messageText;
}
}
}
পদ্ধতিটি কল করার আর একটি ক্লাস:
namespace Blokick.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MessagePerson : ContentPage
{
SignalRConnectProvider signalR = new SignalRConnectProvider();
public MessagePerson()
{
InitializeComponent();
signalR.IsStopRequested = true; // 2-) And this. Make true if running the task and go inside if statement of the IsStopRequested property.
if (signalR.ChatHubProxy != null)
{
signalR.Disconnect();
}
LoadSignalRMessage();
}
}
}
আপনি যদি কোনও কাজটি তার নিজের থ্রেডে তৈরি করতে এবং Abort
তার Thread
অবজেক্টটিতে কল করতে পারেন তবে আপনি থ্রেডের মতো কোনও কাজকে বাতিল করতে পারেন । ডিফল্টরূপে, একটি টাস্ক একটি থ্রেড পুল থ্রেড বা কলিং থ্রেডে চালিত হয় - যার মধ্যে আপনি সাধারণত বাতিল করতে চান না।
কার্যটি নিজস্ব থ্রেড পেয়েছে তা নিশ্চিত করতে, থেকে প্রাপ্ত একটি কাস্টম শিডিয়ুলার তৈরি করুন TaskScheduler
। আপনার প্রয়োগে QueueTask
, একটি নতুন থ্রেড তৈরি করুন এবং কার্য সম্পাদন করতে এটি ব্যবহার করুন। পরবর্তীতে, আপনি থ্রেড, যা একটি সঙ্গে একটি সমালোচনা রাজ্যের সম্পন্ন টাস্ক কারণ হবে বাতিল করতে ThreadAbortException
।
এই টাস্ক শিডিয়ুলারটি ব্যবহার করুন:
class SingleThreadTaskScheduler : TaskScheduler
{
public Thread TaskThread { get; private set; }
protected override void QueueTask(Task task)
{
TaskThread = new Thread(() => TryExecuteTask(task));
TaskThread.Start();
}
protected override IEnumerable<Task> GetScheduledTasks() => throw new NotSupportedException(); // Unused
protected override bool NotSupportedException(Task task, bool taskWasPreviouslyQueued) => throw new NotSupportedException(); // Unused
}
আপনার কাজটি এভাবে শুরু করুন:
var scheduler = new SingleThreadTaskScheduler();
var task = Task.Factory.StartNew(action, cancellationToken, TaskCreationOptions.LongRunning, scheduler);
পরে, আপনি এর সাথে গর্ভপাত করতে পারেন:
scheduler.TaskThread.Abort();
নোট করুন যে কোনও থ্রেড বাতিল করার বিষয়ে সতর্কতা এখনও প্রযোজ্য:
Thread.Abort
পদ্ধতি সাবধানতার সাথে ব্যবহার করা উচিত। বিশেষত আপনি যখন বর্তমান থ্রেড ব্যতীত অন্য কোনও থ্রেডকে বাতিল করতে বলেছেন, তখন আপনি কী জানেন যে থ্রডঅবর্টেক্সপশন নিক্ষেপ করা হলে কোন কোড কার্যকর করেছে বা কার্যকর করতে ব্যর্থ হয়েছে , না আপনি নিজের অ্যাপ্লিকেশন বা কোনও অ্যাপ্লিকেশন এবং ব্যবহারকারীর অবস্থা সম্পর্কে নিশ্চিত হতে পারবেন এটি সংরক্ষণের জন্য দায়ী। উদাহরণস্বরূপ, কলিংThread.Abort
স্থিতিশীল নির্মাতাদের কার্যকর হতে বাধা দিতে পারে বা পরিচালনা না করে থাকা সংস্থাগুলির মুক্তি আটকাতে পারে।
Thread.Abort
এটি .NET কোর সমর্থিত নয়। এটির ব্যবহারের চেষ্টা এখানে ব্যতিক্রমের ফলাফল: সিস্টেম.প্লাটফর্ম নটসপোর্টড এক্সসেপশন: এই প্ল্যাটফর্মে থ্রেড অ্যাওর্ট সমর্থিত নয়। একটি তৃতীয় সতর্কতা হ'ল SingleThreadTaskScheduler
প্রতিশ্রুতি-শৈলীর কার্যগুলির সাথে async
ডেলিগেটসদের সাথে তৈরি টাস্কগুলির সাথে কার্যকরভাবে ব্যবহার করা যাবে না । উদাহরণস্বরূপ একটি এম্বেড await Task.Delay(1000)
থাকা কোনও থ্রেডে চালিত হয় না, সুতরাং এটি থ্রেড ইভেন্টগুলি থেকে প্রভাবিত হবে।