-2
我想用真正的同步方法創建一個類庫,所以我想避免實現一個只使用Task.Run來運行同步代碼的假異步方法。如何實現真正的異步方法?
我已經看到,一個方法是這樣:
public Task miMethodAsync()
{
TaskCompletionSource<bool> miTcs = new TaskCompletionSource<bool>();
new Timer(_ =>
{
for (Int64 i = 1; i < 10000000; i++)
{
//todo my long code
}
miTcs.SetResult(true);
})
.Change(0, Timeout.Infinite);
return miTcs.Task;
}
該解決方案使用計時器返回的任務,然後在0毫秒後,它將運行在定時器中的代碼。
此解決方案不會創建新任務,因此它不會佔用線程表單線程池,因此可擴展性很好。但我認爲這個解決方案,使用定時器來運行同步代碼,這不是一個優雅的解決方案,所以我想知道我能夠實現一個真正的異步方法。
因爲這個解決方案還我可以有我的同步方法,只是實現這種方式ASYN方法:
public Task myMethodAsync()
{
TaskCompletionSource<bool> miTcs = new TaskCompletionSource<bool>();
new Timer(_ =>
{
myMethodSync();
miTcs.SetResult(true);
})
.Change(0, Timeout.Infinite);
return miTcs.Task;
}
但正如我的評論,我覺得這不是一個完美的解決方案,但實際上它似乎不是像我在Task.Run()方法內運行同步代碼時那樣的僞異步方法。
如果計時器代碼在同一個線程中運行(並且這是一個UI線程)並且運行時間很長,它仍然會凍結UI。如果;然而,計時器會創建一個新的線程,通過使用計時器隱藏這個線程,您獲得了什麼? –
只要同步方法正在運行,這將用盡一個線程。無論這是活動線程,UI線程還是線程池線程,都取決於您正在使用的.NET庫中名爲Timer的六個類中的哪一個,以及哪個線程調用myMethodAsync()。 –
你可以詳細說明爲什麼你想在同步代碼中創建一個'async'包裝嗎?假設你閱讀引用的帖子[從你最後一個問題](https://stackoverflow.com/questions/46845005/is-it-really-a-bad-idea-to-use-threads-in-a-class-library )你知道這是一個壞主意。你是否正在履行「任務」返回界面?如果是,則返回'Task.FromResult'或'Task.CompletedTask',並再次讓客戶決定何時卸載該進程。沒有更多的細節,你會得到以前的建議,即[**不要做**](https://stackoverflow.com/a/32642687/7339946)。 – JSteward