c# - मैं टीपीएल कार्यों को निरस्त/रद्द कैसे करूं?




.net multithreading (8)

Task.Factory.StartNew () में किसी अज्ञात विधि का उपयोग न करने पर CancellationTokens का उपयोग करने के तरीके के बारे में प्रेरक के के प्रश्न का उत्तर देने के लिए, आप MSNN उदाहरण में दिखाए गए तरीके से प्रारंभिक विधि में पैरामीटर के रूप में रद्द करने के लिए पास कर सकते हैं, जैसा कि MSNN उदाहरण में दिखाया गया है here

जैसे

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, 

}

धागे में, मैं कुछ System.Threading.TaskSystem.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();
    }
}

इस तरह की चीज तर्कसंगत कारणों में से एक है कि Abort को बहिष्कृत क्यों किया जाता है। सबसे पहले और सबसे महत्वपूर्ण, यदि संभव हो तो थ्रेड को रद्द या बंद करने के लिए Thread.Abort() का उपयोग न करें। Abort() उपयोग केवल उस थ्रेड को मजबूर करने के लिए किया जाना चाहिए जो समय पर फैशन में रोकने के लिए अधिक शांतिपूर्ण अनुरोधों का जवाब नहीं दे रहा है।

ऐसा कहा जा रहा है कि, आपको साझा रद्दीकरण संकेतक प्रदान करने की आवश्यकता है कि एक थ्रेड सेट करता है और प्रतीक्षा करता है जबकि अन्य थ्रेड समय-समय पर जांचता है और कृपा से बाहर निकलता है। .NET 4 में विशेष रूप से इस उद्देश्य, CancellationToken लिए डिज़ाइन की गई संरचना शामिल है।


एक कार्य को छोड़ना आसानी से संभव है यदि आप उस थ्रेड को कैप्चर करते हैं जिसमें कार्य चल रहा है। यह उदाहरण दिखाने के लिए एक उदाहरण कोड है:

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();
}

मैंने टास्क.रुन () का उपयोग इस के लिए सबसे आम उपयोग-केस दिखाने के लिए किया - पुराने सिंगल-थ्रेडेड कोड के साथ कार्य के आराम का उपयोग करके, जो यह रद्द करने के लिए रद्द किया जाना चाहिए या नहीं, यह रद्द करने के लिए रद्द करना टोकन स्रोत वर्ग का उपयोग नहीं करता है।


कार्य थ्रेडपूल पर निष्पादित किया जा रहा है (कम से कम, यदि आप डिफ़ॉल्ट फैक्ट्री का उपयोग कर रहे हैं), तो थ्रेड को निरस्त करने से कार्यों को प्रभावित नहीं किया जा सकता है। कार्यों को निरस्त करने के लिए, एमएसडीएन पर Cancellation देखें।


मैं एक कार्य रद्द करने के लिए एक मिश्रित दृष्टिकोण का उपयोग करें।

  • सबसे पहले, मैं Cancellation का उपयोग करके इसे विनम्रता से रद्द करने की कोशिश कर रहा हूं।
  • यदि यह अभी भी चल रहा है (उदाहरण के लिए डेवलपर की गलती के कारण), तो पुराने स्कूल Abort विधि का उपयोग करके इसे दुर्व्यवहार करें और मार दें।

नीचे एक उदाहरण चेकआउट करें:

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();
        }
    }
}

Cancellation माध्यम से Cancellation लिए कार्य प्रथम श्रेणी का समर्थन है। रद्दीकरण टोकन के साथ अपने कार्यों को बनाएँ, और इन कार्यों को स्पष्ट रूप से रद्द करें।


इस पोस्ट की तरह सुझाव है, यह निम्नलिखित तरीके से किया जा सकता है:

int Foo(CancellationToken token)
{
    Thread t = Thread.CurrentThread;
    using (token.Register(t.Abort))
    {
        // compute-bound work here
    }
}

हालांकि यह काम करता है, इस तरह के दृष्टिकोण का उपयोग करने की सिफारिश नहीं की जाती है। यदि आप कार्य में निष्पादित कोड को नियंत्रित कर सकते हैं, तो आप रद्दीकरण के उचित संचालन के साथ बेहतर तरीके से जाना चाहेंगे।





abort