以线程或任务方式启动异步方法

Kin*_*sin 7 c# asynchronous webrequest async-await

我是新来的C#小号await/async,目前玩弄了一下.

在我的场景中,我有一个简单的客户端对象,它有一个WebRequest属性.客户端应该通过WebRequests 定期发送活动消息RequestStream.这是client-object的构造函数:

public Client()
{
    _webRequest = WebRequest.Create("some url");
    _webRequest.Method = "POST";

    IsRunning = true;

    // --> how to start the 'async' method (see below)
}
Run Code Online (Sandbox Code Playgroud)

和async alive-sender方法

private async void SendAliveMessageAsync()
{
    const string keepAliveMessage = "{\"message\": {\"type\": \"keepalive\"}}";
    var seconds = 0;
    while (IsRunning)
    {
        if (seconds % 10 == 0)
        {
            await new StreamWriter(_webRequest.GetRequestStream()).WriteLineAsync(keepAliveMessage);
        }

        await Task.Delay(1000);
        seconds++;
    }
}
Run Code Online (Sandbox Code Playgroud)

该方法应该如何开始?

new Thread(SendAliveMessageAsync).Start();

要么

Task.Run(SendAliveMessageAsync); //将返回类型更改为Task

要么

等待SendAliveMessageAsync(); //失败,因为构造函数不是异步的

我的问题更多的是我个人的理解await/async,我认为在某些方面可能是错的.

第三种选择是投掷

The 'await' operator can only be used in a method or lambda marked with the 'async' modifier
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 7

该方法应该如何开始?

我投票赞成"以上都不是".:)

"火与忘记"是一个难以正确处理的场景.特别是,错误处理总是有问题的.在这种情况下,async void可能会让您感到惊讶

如果我不await立即执行任务,我更愿意明确保存任务:

private async Task SendAliveMessageAsync();

public Task KeepaliveTask { get; private set; }

public Client()
{
  ...
  KeepaliveTask = SendAliveMessageAsync();
}
Run Code Online (Sandbox Code Playgroud)

这至少允许消费者Client检测并从该SendAliveMessageAsync方法抛出的异常中恢复.

另外,这种模式几乎等同于我的"异步初始化"模式.


Joh*_*ord 5

编辑为以前的答案是错误的:

由于它在构造函数中,我认为您必须为它启动一个新线程。我个人会使用

Task.Factory.StartNew(() => SendAliveMessageAsync());


Dom*_*see 0

由于这是一次即发即忘操作,因此您应该使用

SendAliveMessageAsync();
Run Code Online (Sandbox Code Playgroud)

请注意,await不会启动新的Task. 等待aTask完成只是语法糖。
使用 启动一个新线程Task.Run

所以在里面SendAliveMessageAsync你应该开始一个新任务:

private async Task SendAliveMessageAsync()
{
    const string keepAliveMessage = "{\"message\": {\"type\": \"keepalive\"}}";
    await Task.Run( () => {
        var seconds = 0;
        while (IsRunning)
        {
            if (seconds % 10 == 0)
            {
                await new StreamWriter(_webRequest.GetRequestStream()).WriteLineAsync(keepAliveMessage);
            }

            await Task.Delay(1000);
            seconds++;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)