2013-07-07 10 views
8

निष्पादित करने के लिए एसिंक कोड को क्यूइंग करना किसी भी समय, मुझे एक विधि कॉल प्राप्त हो सकती है जिसे संतुष्ट करने के लिए लंबे समय तक चलने वाले ऑपरेशन की आवश्यकता होगी।क्रमशः

इनमें से कई विधियां हैं। चूंकि वे संसाधन साझा करते हैं, इसलिए यह महत्वपूर्ण है कि वे एक साथ नहीं चलें - प्रत्येक अनुक्रम में चलना चाहिए।

आम तौर पर, मैं बस अनुक्रम में कॉल करने चाहते हैं:

var result1 = await Foo1Async(); 
var result2 = await Foo2Async(); 

हालांकि, इस मामले में, विधि मेरे लिए कॉल अतुल्यकालिक हैं:

void Bar1() 
{ 
    var result = await Foo1Async(); 
    // ... 
} 

void Bar2() 
{ 
    var result = await Foo2Async(); 
    // ... 
} 

मुझे लगता है मैं उपयोग करने की आवश्यकता Task.ContinueWith, और इस के साथ आए हैं:

readonly object syncLock = new Object(); 

private Task currentOperationTask = TaskUtilities.CompletedTask; 
public Task<TResult> EnqueueOperation<TResult>(Func<Task<TResult>> continuationFunction) 
{ 
    lock (this.syncLock) 
    { 
     var operation = this.currentOperationTask.ContinueWith(predecessor => continuationFunction()).Unwrap(); 
     this.currentOperationTask = operation; 
     return operation; 
    } 
} 

और मैं इसे इस तरह का उपयोग करें:

void Bar1() 
{ 
    var result = await EnqueueOperation(() => Foo1Async()); 
    // ... 
} 

void Bar2() 
{ 
    var result = await EnqueueOperation(() => Foo2Async()); 
    // ... 
} 

क्या यह इस समस्या से संपर्क करने का सही तरीका है? क्या कोई नुकसान है जिसके बारे में मुझे अवगत होना चाहिए?

+0

मैं उस के साथ किसी भी समस्या नहीं दिख रहा है, लेकिन मैं आपको लगता है कि खो सकता है '() =>' अगर आप अपने हस्ताक्षर को बदलने '(कार्य निरंतरता समारोह)'। – SimpleVar

+0

@YoryeNathan यह काम नहीं करेगा, इसका मतलब यह होगा कि प्रत्येक एसिंक विधि तुरंत निष्पादित करना शुरू कर देगी, सवाल यह है कि इससे कैसे बचें। – svick

+0

बीटीडब्लू, यदि आपका कोड वास्तव में ऐसा दिखता है, तो आप केवल 'एंटीयूऑपरेशन (Foo1Async) का इंतजार कर सकते हैं;' (लैम्ब्डा के बिना)। – svick

उत्तर

1

आपका कोड ठीक काम करेगा, मुझे लगता है कि यह समस्या हल करने का एक उचित तरीका है।

यह करने के लिए एक सरल दृष्टिकोण का उपयोग करने AsyncLock from Nito AsyncEx होगा:

private readonly AsyncLock asyncLock = new AsyncLock(); 

public async Task<TResult> EnqueueOperation<TResult>(
    Func<Task<TResult>> continuationFunction) 
{ 
    using (await asyncLock.LockAsync()) 
    { 
     return await continuationFunction(); 
    } 
} 
+0

क्या यह 'एनक्यूऑपरेशन' कॉल से संबंधित कार्यों के लिए भी इंतजार करेगा? – SimpleVar

+0

@YoryeNathan नहीं, यह नहीं होगा। लेकिन यदि आप यूआई थ्रेड से 'एनक्यूऑपरेशन() 'को कॉल करते हैं, तो वह वहां' निरंतरता समारोह 'भी लगाएगा, जो आप नहीं चाहते हैं। – svick

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