簡體   English   中英

一個Task的Output輸入到另一個Task

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM