2015-11-22 12 views
7

.NET 4.5.1: ऐसा प्रतीत होता है, मैं रद्द करने के लिए रद्द किए गए एक ब्लॉकिंग विधि को रद्द नहीं कर सकता, रद्द किए गए टाइमआउट स्रोत का उपयोग कर।सी #: रद्दीकरण टोकन ब्लॉकिंग विधि को रद्द नहीं करता है

class Program 
{ 
    static void Main(string[] args) 
    { 
     var cts = new System.Threading.CancellationTokenSource(); 

     System.Console.CancelKeyPress += (s, e) => 
     { 
      e.Cancel = true; 
      cts.Cancel(); 
     }; 

     MainAsync(args, cts.Token).Wait(); 
    } 

    // MainAsync from http://stackoverflow.com/questions/9208921/async-on-main-method-of-console-app 
    static async Task MainAsync(string[] args, System.Threading.CancellationToken token) 
    { 
     Console.WriteLine("Starting MainAsync"); 
     var cts = new System.Threading.CancellationTokenSource(3000); 
     var task = Task.Factory.StartNew(() => 
     { 
      Console.WriteLine("Starting task..."); 
      var t = new System.Net.Sockets.TcpClient(); 
      var buffer = new byte[t.ReceiveBufferSize]; 
      t.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1337)); 

      Console.WriteLine("Recieving..."); 
      t.Client.Receive(buffer); 
      Console.WriteLine("Finished Recieving..."); 

      return true; 
     }, cts.Token); 

     var success = await task; 

     Console.WriteLine("Did the task complete succesfuly?", success); 
    } 
} 

निहित, सही उदाहरण (मुझे आशा है कि यह सही है) के ऊपर कम, स्व से उत्पादन होता है:

Starting MainAsync 
Starting task... 
Recieving... 

कार्य क्यों रद्द नहीं करता है, कोई अपवाद नहीं फेंक दिया जाता है?

+0

सॉकेट.रेसीव का उपयोग करके आप यहां उपयोग कर रहे हैं एक अवरोधक कॉल है - आपको एक टाइमआउट या एसिंक उपयोग प्रदान करना चाहिए ताकि आप प्रसंस्करण के दौरान रद्दीकरण को फिर से मूल्यांकन कर सकें। रद्दीकरण टोकन आपके लिए अवरुद्ध कॉल को जादुई रूप से समाप्त नहीं करेगा। – Joe

उत्तर

4

मैं अपने ब्लॉग पर राज्य के रूप में, "You keep using that CancellationToken there. I do not think it means what you think it means."

विशेष रूप से, CancellationTokenStartNew के लिए पारित केवल शुरू करने प्रतिनिधि के रद्द हो जाएगा। यदि आप प्रतिनिधि को रद्दीकरण का समर्थन करने के लिए चाहते हैं, तो प्रतिनिधि को खुद को CancellationToken का पालन करना होगा।

3

मुझे यकीन नहीं है, लेकिन मुझे लगता है कि आप "रद्दीकरण का अनुरोध कर रहे हैं" को "थ्रेड/टास्क को समाप्त करने या रद्द करने" के साथ भ्रमित कर रहे हैं। ये दो पूरी तरह से अलग चीजें हैं। Canellation in Managerd Threads के विवरण के अनुसार प्रदान की गई कार्यक्षमता आपको सिग्नल की तरह कुछ भेजने में सक्षम बनाती है, यह दर्शाती है कि प्रगति पर कार्रवाई बंद हो जाएगी।

एक सिग्नल पर आप कैसे और यदि प्रतिक्रिया करते हैं - एक प्रोग्रामर के रूप में - आप तक।

अपने उदाहरण में आप एक नया कार्य

var task = Task.Factory.StartNew(() => 
{  
    Console.WriteLine("Starting task..."); 
    var t = new System.Net.Sockets.TcpClient(); 
    var buffer = new byte[t.ReceiveBufferSize]; 
    t.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1337)); 

    Console.WriteLine("Recieving..."); 
    t.Client.Receive(buffer); 
    Console.WriteLine("Finished Recieving..."); 

    return true; 
}, cts.Token); 

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

आप जो चाहते हैं वह वर्तमान कार्य के पीछे धागे को त्यागना है जो मेरी राय में केवल Thread कक्षा का एक नया उदाहरण बनाकर और उसके अनुसार गर्भपात को संभालने के द्वारा संभव है।

संबंधित मुद्दे