简体   繁体   English

一个Task的Output输入到另一个Task

[英]Output of one Task input to other Task

In Winforms, I have following: ProcessClientAsync adds an element to a ConcurrentDictionary.在 Winforms 中,我有以下内容: ProcessClientAsync 将元素添加到 ConcurrentDictionary。 How can I ensure that the forloop runs after the Task.Run().如何确保 forloop 在 Task.Run() 之后运行。 I tried to remove ConfigureAwait but it freezes the UI.我试图删除 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;
}

You could await the Task.Run , but make sure to make the parent method async您可以等待Task.Run ,但请确保使父方法异步

await Task.Run(() => ProcessClientAsync(client).ConfigureAwait(false));

This will wait for the async task to complete, and then execute the rest of the code.这将等待异步任务完成,然后执行代码的rest。 I would suggest learning a bit more about async/await.我建议多学习一些关于 async/await 的知识。

To block the ProcessClientAsync call you can do the following:要阻止 ProcessClientAsync 调用,您可以执行以下操作:

Task.Run(() => ProcessClientAsync(client)).Wait();

If you want to access the result of ProcessClientAsync:如果要访问 ProcessClientAsync 的结果:

Task<TResult> task = null;
Task.Run(() => task = ProcessClientAsync(client)).Wait();

// task.Result contains the result

Even if this works, it's recommended to await tasks rather than blocking with wait.即使这样可行,建议等待任务而不是等待阻塞。

Quiz, what is the type of the variable x below?测验,下面的变量x的类型是什么?

var x = Task.Run(() => Task.Delay(1000).ConfigureAwait(false));

The type is not Task .类型不是Task It is Task<ConfiguredTaskAwaitable> .它是Task<ConfiguredTaskAwaitable> That internal ConfigureAwait(false) call is not only meaningless, but it also created a unexpected situation where the return value must now be awaited twice:内部的ConfigureAwait(false)调用不仅没有意义,而且还造成了一个意想不到的情况,即现在必须等待返回值两次:

await await x;

Don't do this.不要这样做。 If you have to use ConfigureAwait(false) for some reason, then you are expected to await the result immediately.如果您出于某种原因必须使用ConfigureAwait(false) ,那么您应该立即await结果。 Don't pass ConfiguredTaskAwaitable structs around.不要传递ConfiguredTaskAwaitable结构。 My advice is to search your code for more instances of this anti-pattern, and eliminate them.我的建议是在你的代码中搜索更多这种反模式的实例,并消除它们。

If you don't want to mark the parent method as async, then you could use the following instead:如果您不想将父方法标记为异步,则可以改用以下方法:

Task.Wait(Task.Run(() => ProcessClientAsync(client)));

This method has several overloads that allow for configurability of cancellation and timeouts as well:此方法有几个重载允许取消和超时的可配置性:
https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.wait?view=netframework-4.8 https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.wait?view=netframework-4.8

Also, if your code actually says while (true) and has no break conditions, then it will never exit.此外,如果您的代码实际上说while (true)并且没有中断条件,那么它将永远不会退出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM