2016-08-17 4 views
30

में बराबर वादा करें स्कैला में एक वादा वर्ग है जिसका उपयोग भविष्य में मैन्युअल रूप से पूरा करने के लिए किया जा सकता है। मैं सी # में एक विकल्प की तलाश में हूं।सी #

मैं एक परीक्षण लिख रहा हूँ और मैं इसे यह कुछ ऐसा दिखाई हैं:

// var MyResult has a field `Header` 
var promise = new Promise<MyResult>; 

handlerMyEventsWithHandler(msg => 
    promise.Complete(msg); 
); 

// Wait for 2 seconds 
var myResult = promise.Future.Await(2000); 

Assert.Equals("my header", myResult.Header); 

मैं समझता हूँ कि यह शायद सी # के लिए सही आकार नहीं है, लेकिन मैं एक उचित उपाय खोजा नहीं कर सका कुछ अलग पैटर्न के साथ भी वही चीज़ प्राप्त करने के लिए।

संपादित करें: कृपया ध्यान दें कि async/await यहां सहायता नहीं करता है, क्योंकि मेरे पास प्रतीक्षा करने का कार्य नहीं है! मेरे पास सिर्फ एक हैंडलर तक पहुंच है जो एक और धागे पर चलाई जाएगी।

+0

की संभावित डुप्लिकेट [कैसे और उपयोग करने के लिए जब \ 'async \' और \ 'का इंतजार \ '] (http://stackoverflow.com/questions/14455293/कैसे-और-कब-उपयोग-async-and-await) – Stijn

+1

मुझे लगता है कि आप 'कार्य ' की तलाश में हैं। –

उत्तर

41

सी # में:

  • Task<T> एक भविष्य (या Task एक यूनिट-लौटने भविष्य के लिए) है।
  • TaskCompletionSource<T> एक वादा है।

तो अपने कोड इस तरह के रूप अनुवाद होगा:

// var promise = new Promise<MyResult>; 
var promise = new TaskCompletionSource<MyResult>(); 

// handlerMyEventsWithHandler(msg => promise.Complete(msg);); 
handlerMyEventsWithHandler(msg => promise.TrySetResult(msg)); 

// var myResult = promise.Future.Await(2000); 
var completed = await Task.WhenAny(promise.Task, Task.Delay(2000)); 
if (completed == promise.Task) 
    ; // Do something on timeout 
var myResult = await completed; 

Assert.Equals("my header", myResult.Header); 

"समय अतुल्यकालिक प्रतीक्षा" थोड़ा अजीब है, लेकिन यह भी वास्तविक दुनिया कोड में अपेक्षाकृत असामान्य है। इकाई परीक्षण के लिए, मैं सिर्फ एक नियमित रूप से अतुल्यकालिक इंतजार करना होगा:

var promise = new TaskCompletionSource<MyResult>(); 

handlerMyEventsWithHandler(msg => promise.TrySetResult(msg)); 

var myResult = await promise.Task; 

Assert.Equals("my header", myResult.Header); 
+0

रद्दीकरण टोकन का उपयोग करके टाइमआउट को कार्यान्वित करने का एक अच्छा तरीका है। Https://stackoverflow.com/q/23476576/1288449 –

+1

@StevenLiekens देखें: मैं मानता हूं कि टाइमआउट आमतौर पर रद्दीकरण टोकन के रूप में बेहतर प्रतिनिधित्व किया जाता है; हालांकि, यह उन स्थितियों के लिए सबसे अच्छा है जहां ऑपरेशन रद्द करने के लिए टाइमआउट का उपयोग किया जाता है। इस परिदृश्य में, हम * प्रतीक्षा * को रद्द करने के बारे में बात कर रहे हैं, * ऑपरेशन * नहीं, और रद्दीकरण टोकन इस परिदृश्य में अधिक अजीब हैं। –

4

आप सी # का उपयोग कर सकते वादे पुस्तकालय

ओपन Github पर sourced: https://github.com/Real-Serious-Games/C-Sharp-Promise

NuGet पर उपलब्ध: https://www.nuget.org/packages/RSG.Promise/

+0

आप मेरे ब्लॉग पर इसके बारे में और अधिक पढ़ सकते हैं: http://www.what-could-possibly-go-wrong.com/promises-for-game-development/ –

6

तीसरे पक्ष के पुस्तकालयों के बिना किसी न किसी तरह सी # बराबर होगा:

// var MyResult has a field `Header` 
var promise = new TaskCompletionSource<MyResult>(); 

handlerMyEventsWithHandler(msg => 
    promise.SetResult(msg) 
); 

// Wait for 2 seconds 
if (promise.Task.Wait(2000)) 
{ 
    var myResult = promise.Task.Result; 
    Debug.Assert("my header" == myResult.Header); 
} 

ध्यान दें कि await/async का उपयोग संभवतः उच्च स्तर के रूप में करने के लिए सबसे अच्छा है। Task के Result तक पहुंचने या Wait का उपयोग कर कुछ मामलों में introduce deadlocks का उपयोग कर सकते हैं।