[英]Output of one Task input to other Task
在 Winforms 中,我有以下內容: ProcessClientAsync 將元素添加到 ConcurrentDictionary。 如何確保 forloop 在 Task.Run() 之后運行。 我試圖刪除 ConfigureAwait,但它凍結了 UI。
public async Task Listen(int port)
{
try
{
IPAddress serverAddress = IPAddress.Parse("127.0.0.1"); // localhost
_listener = new TcpListener(serverAddress, port);
_listener.Start();
while (true)
{
TcpClient tcpClient = await _listener.AcceptTcpClientAsync();
await Task.Run(() => ProcessTcpClientAsync(tcpClient).ConfigureAwait(false));
_statusText.StatusUpdate = "number of users are " + _mapClient.GetUsers().Count;
}
}
catch (SocketException ex)
{
string message = string.Format("Error listening on port {0}. Make sure IIS or another application is not running and consuming your port.", port);
throw new Exception(message, ex);
}
}
private async Task<string> ProcessTcpClientAsync(TcpClient tcpClient)
{
string key = string.Empty;
WebSocket webSocket = null;
try
{
if (_isDisposed)
return string.Empty;
// this worker thread stays alive until either of the following happens:
// Client sends a close conection request OR
// An unhandled exception is thrown OR
// The server is disposed
// get a secure or insecure stream
NetworkStream stream = tcpClient.GetStream();
WebSocketHttpContext context = await _webSocketServerFactory.ReadHttpHeaderFromStreamAsync(stream);
if (context.IsWebSocketRequest)
{
key = GetKeyFromContext(context);
// _statusText.StatusUpdate = "Connection from origin.";
webSocket = await _webSocketServerFactory.AcceptWebSocketAsync(context);
//_statusText.StatusUpdate = "Connection accepted.";
await RespondToWebSocketRequestAsync(tcpClient, key, webSocket);
}
else
{
//_statusText.StatusUpdate = "Http header contains no web socket upgrade request. Ignoring...";
}
}
catch (Exception ex)
{
}
finally
{
try
{
await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closed in server by the client", CancellationToken.None);
tcpClient.Client.Close();
tcpClient.Close();
}
catch (Exception ex)
{
}
}
return key;
}
您可以等待Task.Run ,但請確保使父方法異步
await Task.Run(() => ProcessClientAsync(client).ConfigureAwait(false));
這將等待異步任務完成,然后執行代碼的rest。 我建議多學習一些關於 async/await 的知識。
要阻止 ProcessClientAsync 調用,您可以執行以下操作:
Task.Run(() => ProcessClientAsync(client)).Wait();
如果要訪問 ProcessClientAsync 的結果:
Task<TResult> task = null;
Task.Run(() => task = ProcessClientAsync(client)).Wait();
// task.Result contains the result
即使這樣可行,建議等待任務而不是等待阻塞。
測驗,下面的變量x
的類型是什么?
var x = Task.Run(() => Task.Delay(1000).ConfigureAwait(false));
類型不是Task
。 它是Task<ConfiguredTaskAwaitable>
。 內部的ConfigureAwait(false)
調用不僅沒有意義,而且還造成了一個意想不到的情況,即現在必須等待返回值兩次:
await await x;
不要這樣做。 如果您出於某種原因必須使用ConfigureAwait(false)
,那么您應該立即await
結果。 不要傳遞ConfiguredTaskAwaitable
結構。 我的建議是在你的代碼中搜索更多這種反模式的實例,並消除它們。
如果您不想將父方法標記為異步,則可以改用以下方法:
Task.Wait(Task.Run(() => ProcessClientAsync(client)));
此方法有幾個重載允許取消和超時的可配置性:
https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.wait?view=netframework-4.8
此外,如果您的代碼實際上說while (true)
並且沒有中斷條件,那么它將永遠不會退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.