为什么我必须使用(异步方法).Result而不是await (async方法)

本文关键字:方法 async await Result 异步方法 为什么 | 更新日期: 2023-09-27 18:12:37

我在mediasservices azure门户中启动了2个通道。启动一个通道需要很长时间才能完成,每个通道大约需要25-30秒。因此,多线程:)

然而,我不清楚以下内容:

我有两个方法:

public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
    {
        var workerThreads = new List<Thread>();
        var results = new List<bool>();
        foreach (var azureProgram in _accounts.GetPrograms(programName))
        {
            var thread = new Thread(() =>
            {
                var result = StartChannelAsync(azureProgram).Result;
                lock (results)
                {
                    results.Add(result);
                }
            });
            workerThreads.Add(thread);
            thread.Start();
        }
        foreach (var thread in workerThreads)
        {
            thread.Join();
        }
        return results.All(r => r);
    }

private async Task<bool> StartChannelAsync(IProgram azureProgram)
    {
        var state = _channelFactory.ConvertToState(azureProgram.Channel.State);
        if (state == State.Running)
        {
            return true;
        }
        if (state.IsTransitioning())
        {
            return false;
        }
        await azureProgram.Channel.StartAsync();
        return true;
    }

在第一种方法中我使用

var result = StartChannelAsync(azureProgram).Result;

在这种情况下,一切都很好。但是如果我使用

var result = await StartChannelAsync(azureProgram);

没有等待执行,我的结果有零项。我遗漏了什么?

这是正确的方法吗?

感谢对代码的任何注释。我不是多线程之王;)

干杯!

为什么我必须使用(异步方法).Result而不是await (async方法)

不要跨新的Thread实例并行执行任务,而是使用Task。WhenAll:

public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
{
    // Create a task for each program and fire them "at the same time"
    Task<bool>[] startingChannels = _accounts.GetPrograms(programName))
                                                        .Select(n => StartChannelAsync(n))
                                                        .ToArray();
    // Create a task that will be completed when all the supplied tasks are done
    bool[] results = await Task.WhenAll(startingChannels);
    return results.All(r => r);
}

注意:我看到你正在传递一个CancellationToken到你的StartAsync方法,但你实际上并没有使用它。考虑将它作为参数传递给StartChannelAsync,然后在调用azureProgram.Channel.StartAsync

时使用它。

如果你喜欢俏皮话:

public async Task<bool> StartAsync(string programName, CancellationToken token = default(CancellationToken))
{
     return (await Task.WhenAll(_accounts.GetPrograms(programName)
                                         .Select(p => StartChannelAsync(p))
                                         .ToArray())).All(r => r);
}