您將如何實現與Async CTP await
關鍵字類似的工作?是否有一個簡單的實現在所有情況下都像await
一樣工作,或者await
是否需要針對不同場景的不同實現?如何在沒有Async CTP的情況下實現等待
回答
await
總是涉及同樣的轉換 - 但這是一個非常痛苦的轉變。 庫一側的await
不是太複雜,但棘手的是,編譯器爲你建立一個狀態機,允許繼續跳回到正確的位置。
這是可能我的一些hacky使用迭代塊(yield return),你可能會僞造類似的東西......但它會非常難看。
我給出了一個DevExpress webinar on what the compiler is doing behind the scenes a few weeks ago - 它顯示了來自兩個示例的反編譯代碼,並解釋了編譯器如何構建一個返回任務,以及「awaiter」必須做什麼。它可能對你有用。
您可以在這裏找到Jon在youtube上提到的網絡研討會:http://www.youtube.com/watch?v=HpA2x_JvLD4 – ShitalShah 2014-03-14 20:34:29
很少有實現和由迭代器(yield)構成的協程示例。
其中一個例子是Caliburn.Micro框架,它使用此模式進行異步GUI操作。但是對於一般的異步代碼,它可以很容易地推廣。
的MindTouch DReAM框架實現協同程序上的迭代器模式的頂部是功能上非常相似,異步/等待:
async Task Foo() {
await SomeAsyncCall();
}
與
IYield Result Foo() {
yield return SomeAsyncCall();
}
Result
是夢的版本Task
。框架DLL可以與.NET 2.0+一起工作,但是爲了構建它,你需要3.5,因爲我們現在使用了很多3.5語法。
新的await
關鍵字與現有的yield return
關鍵字具有類似的語義,因爲它們都會使編譯器爲您生成連續樣式狀態機。所以有可能使用具有與Async CTP相同的行爲的迭代器一起破解一些東西。
這是它的樣子。
public class Form1 : Form
{
private void Button1_Click(object sender, EventArgs e)
{
AsyncHelper.Invoke<bool>(PerformOperation);
}
private IEnumerable<Task> PerformOperation(TaskCompletionSource<bool> tcs)
{
Button1.Enabled = false;
for (int i = 0; i < 10; i++)
{
textBox1.Text = "Before await " + Thread.CurrentThread.ManagedThreadId.ToString();
yield return SomeOperationAsync(); // Await
textBox1.Text = "After await " + Thread.CurrentThread.ManagedThreadId.ToString();
}
Button2.Enabled = true;
tcs.SetResult(true); // Return true
}
private Task SomeOperationAsync()
{
// Simulate an asynchronous operation.
return Task.Factory.StartNew(() => Thread.Sleep(1000));
}
}
由於yield return
產生IEnumerable
我們的協同程序必須返回一個IEnumerable
。所有的魔法都發生在AsyncHelper.Invoke
方法中。這就是我們的協同程序(僞裝成黑客的迭代器)。需要特別注意的是,確保迭代器總是在當前同步上下文中執行(如果存在的話),這在試圖模擬await
如何在UI線程上工作時很重要。它通過同步執行第一個MoveNext
,然後使用SynchronizationContext.Send
從工作線程完成其餘工作,該工作線程也用於在各個步驟中異步等待。
public static class AsyncHelper
{
public static Task<T> Invoke<T>(Func<TaskCompletionSource<T>, IEnumerable<Task>> method)
{
var context = SynchronizationContext.Current;
var tcs = new TaskCompletionSource<T>();
var steps = method(tcs);
var enumerator = steps.GetEnumerator();
bool more = enumerator.MoveNext();
Task.Factory.StartNew(
() =>
{
while (more)
{
enumerator.Current.Wait();
if (context != null)
{
context.Send(
state =>
{
more = enumerator.MoveNext();
}
, null);
}
else
{
enumerator.MoveNext();
}
}
}).ContinueWith(
(task) =>
{
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(default(T));
}
});
return tcs.Task;
}
}
有關TaskCompletionSource
整個位是我在複製的方式await
可以「迴歸」的值的嘗試。問題是協程有實際返回IEnumerable
,因爲它只不過是一個被黑的迭代器。所以我需要想出一個替代機制來捕獲返回值。
這有一些明顯的侷限性,但我希望這給你的一般想法。它還演示了CLR如何使用一個泛化機制來實現協同程序,其中await
和yield return
將以無處不在的方式使用,但以不同的方式提供它們各自的語義。
從我的閱讀中,yield return
和await
之間的主要區別是,await
可以明確地返回一個新的值到延續。
SomeValue someValue = await GetMeSomeValue();
而與yield return
,你必須通過引用來完成同樣的事情。
var asyncOperationHandle = GetMeSomeValueRequest();
yield return asyncOperationHandle;
var someValue = (SomeValue)asyncOperationHandle.Result;
比爾·瓦格納從微軟寫道:an article in MSDN Magazine有關如何使用任務並行庫在Visual Studio 2010中實現異步樣的行爲不會對異步CTP添加依賴。
它採用Task
和Task<T>
廣泛裏面也有額外的好處,一旦C#5已經出來了,你的代碼將做好準備開始使用async
和await
。
- 1. 如何在這種情況下實現線程等待通知?
- 2. AsyncTask如何在沒有deadLock的情況下等待另一個
- 3. CakePHP 3,如何在沒有CTP的情況下渲染
- 4. Visual Studio | Windows Phone在沒有睡眠的情況下等待
- 5. 如何在沒有actionview的情況下實現form_tag helpers?
- 6. 如何在沒有setter的情況下實現INotifyPropertyChanged?
- 7. 我們如何在沒有SpingIOC.jar的情況下實現Spring IOC
- 8. 如何在沒有實現的情況下在android中實現微調器?
- 9. 如何在沒有睡眠的情況下等待5分鐘的PHP
- 10. 我可以在不破壞任何東西的情況下安裝Async CTP嗎?
- 11. 如何在沒有異步/等待的情況下循環異步方法
- 12. 如何在沒有等待SimPy的情況下定期生成活動?
- 13. Nancy:如何在沒有上下文的情況下呈現Html
- 14. 如何在不進行輪詢的情況下等待線程?
- 15. 如何在未等待的情況下輪詢未來狀態?
- 16. 如何在不等待ssh2的情況下強制加載PHP
- 17. 如何在不等待的情況下使用未來?
- 18. 如何在不拋出TaskCanceledExceptions的情況下等待任務?
- 19. 如何在不等待的情況下調用異步函數?
- 20. 如何在不等待輸出的情況下繼續CompletableFuture
- 21. 如何在沒有實體框架的情況下實現Odata API?
- 22. 如何在沒有localStream的情況下創建對等連接?
- 23. 在沒有$ _SESSIONs的情況下實現Facebook PHP SDK(3.1.1)
- 24. 在沒有va_list的情況下實現printf
- 25. 在沒有第三方框架的情況下實現DI
- 26. 我可以在沒有MembershipProvider的情況下實現RoleProvider嗎?
- 27. 在沒有模型的情況下實現MVC架構
- 28. 在沒有JQuery的情況下實現onclick事件
- 29. 在沒有XML配置的情況下實現Spring Security Oauth
- 30. 我們如何在沒有任何實現的情況下使用getApplicationContext()?
我剛剛發表了一篇關於如何[使用迭代器在C#4中等待任務]的文章(http://www.codeproject.com/Articles/504197/Await-Tasks-in-Csharp4-using-Iterators)。令人驚訝的是,它既不是「哈克」也不是非常醜陋,AFAICT就像等待。一探究竟! – 2012-12-08 21:33:36