我試圖理解 David Fowler在這里Task.Factory.StartNew所說的 。TaskCreationOptions.LongRunning
?? 注意:不要將 TaskCreationOptions.LongRunning 與異步代碼一起使用,因為這將創建一個新執行緒,該執行緒將在第一次等待后被銷毀。
我知道在這種情況下沒有任何意義,Task.Run因為Task.Factory.StartNewSendLoopAsync 和 ReceiveLoopAsync 是完全異步的。我也知道,如果其中任何一個方法中存在耗時的同步部分,則 Task.Run/Task.Factory.StartNew 應該在該方法中。
大衛福勒在他的宣告中是什么意思?不應該TaskCreationOptions.LongRunning來自異步任務?或者他的意思是 SendLoopAsync/ReceiveLoopAsync 不應該是異步的?我也知道 TaskCreationOptions.LongRunning 意味著任務將立即啟動,而只有由調度程式安排的普通任務并非如此,并且可能需要一些時間才能結束。您可以在同時啟動多個連接時注意到此行為,這會導致發送和接收回圈以顯著延遲開始。
public async Task StartAsync(CancellationToken cancellationToken)
{
_ = Task.Factory.StartNew(_ => SendLoopAsync(cancellationToken), TaskCreationOptions.LongRunning, cancellationToken);
_ = Task.Factory.StartNew(_ => ReceiveLoopAsync(cancellationToken), TaskCreationOptions.LongRunning, cancellationToken);
}
private async Task SendLoopAsync()
{
await foreach (var message in _outputChannel.Reader.ReadAllAsync(_cancellationSource?.Token))
{
if (_clientWebSocket.State == WebSocketState.Open)
{
await _clientWebSocket.SendAsync(message.Data.AsMemory(), message.MessageType, true, CancellationToken.None).ConfigureAwait(false);
}
}
}
uj5u.com熱心網友回復:
David Fowler的意思是SendLoopAsync/ReceiveLoopAsync不應該是異步的。LongRunning如果該任務將使用啟動執行緒持續以納秒為單位測量的持續時間,那么啟動任務是沒有意義的。發明它ThreadPool是為了準確處理這些型別的情況。如果ThreadPool由于飽和而回應不夠快,那么嘗試找到飽和的原因并修復它是更合乎邏輯的做法,而不是繞過ThreadPool, 并在每次有幾微秒的作業量時創建新執行緒做。
LongRunning這是與 async 結合使用時發生的情況的演示:
var stopwatch = Stopwatch.StartNew();
Thread workerThread = null;
List<(string, long, System.Threading.ThreadState)> entries = new();
Task<Task> taskTask = Task.Factory.StartNew(async () =>
{
workerThread = Thread.CurrentThread;
entries.Add(("A", stopwatch.ElapsedMilliseconds, workerThread.ThreadState));
await Task.Delay(500);
entries.Add(("D", stopwatch.ElapsedMilliseconds, workerThread.ThreadState));
}, default, TaskCreationOptions.LongRunning, TaskScheduler.Default);
taskTask.Wait();
entries.Add(("B", stopwatch.ElapsedMilliseconds, workerThread.ThreadState));
workerThread.Join();
entries.Add(("C", stopwatch.ElapsedMilliseconds, workerThread.ThreadState));
await taskTask.Unwrap();
entries.Add(("E", stopwatch.ElapsedMilliseconds, workerThread.ThreadState));
foreach (var (title, elapsed, state) in entries)
Console.WriteLine($"{title } after {elapsed,3} msec worker thread is {state}");
輸出:
A after 2 msec worker thread is Background
B after 6 msec worker thread is Background, Stopped
C after 6 msec worker thread is Stopped
D after 507 msec worker thread is Stopped
E after 507 msec worker thread is Stopped
在 Fiddle 上試試。
作業執行緒的生命周期最多為 6 毫秒。它真正需要做的就是實體化一個異步狀態機,并使用System.Threading.Timer組件安排回呼。對于如此微小的作業量,6 毫秒在我看來就像一個 eon。很可能這 6 毫秒用于執行緒間通信以及執行緒的創建和銷毀。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/458733.html
