C# 使用async/await运行多个无限循环

C# 使用async/await运行多个无限循环,c#,.net,asynchronous,async-await,xamarin,C#,.net,Asynchronous,Async Await,Xamarin,我正在开发基于xamarin和.net 5 async/awaits的android messanger应用程序 在我的应用程序中,我有生产者/消费者模式来处理无限循环中生成的消息 例如ReadTcpClientAsync producer: async Task ReadTcpClientAsync(CancellationToken cancellationToken) { cde.Signal(); while (!cancellationToken.IsCancellat

我正在开发基于xamarin和.net 5 async/awaits的android messanger应用程序

在我的应用程序中,我有生产者/消费者模式来处理无限循环中生成的消息

例如ReadTcpClientAsync producer:

async Task ReadTcpClientAsync(CancellationToken cancellationToken)
{
    cde.Signal();
    while (!cancellationToken.IsCancellationRequested)
    {
        byte[] buffer = await atc.ReadAsync(cancellationToken);
        // queue message...
    }
}
或SendStatementAsync使用者,用于删除消息并等待WriteAsync

private async Task SendStatementsAsync(CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        var nextItem = await _outputStatements.Take();
        cancellationToken.ThrowIfCancellationRequested();
        // misc ...
        await atc.WriteAsync(call.Serialize());
    }
}
一些消费者只是等待接听电话

 var update = await _inputUpdateStatements.Take();
这种构造在测试中非常有效,但有一种方法我认为我犯了一个巨大的错误。 此方法旨在运行整个客户端后端,同时启动3个pro/con(true)循环

这是:

public async Task RunAsync()
{
   _isRunning = true;
   _progress.ProgressChanged += progress_ProgressChanged;
    await InitMTProto(_scheme).ConfigureAwait(false); // init smth...
    // various init stuf...     
    await atc.ConnectAsync().ConfigureAwait(false); // open connection async
    // IS IT WRONG?
    try
    {                                   
        await Task.WhenAny(SendStatementsAsync(_cts.Token),
                               ReadTcpClientAsync(_cts.Token),
                               ProcessUpdateAsync(_cts.Token, _progress)).ConfigureAwait(false);
    }
    catch (OperationCanceledException oce)
    {   

    }
    catch (Exception ex)
    {

    }
}
暂时忘掉android,想想UI上下文中的任何UI(WinForm、WPF等)OnCreate方法调用RunAsync

protected async override void OnCreate(Bundle bundle)
{
    // start RA 
    await client.RunAsync()
    // never gets here - BAD, but nonblock UI thread - good
    Debug.WriteLine("nevar");
}
因此,正如您所看到的,存在一个问题。在RunAsync wait调用之后,我无法执行任何操作,因为它永远不会从Task.WhenAny(…)返回。我需要在那里执行状态检查,但我需要启动此pro/cons方法,因为我的检查等待ManualResetEvent:

if (!cde.Wait(15000))
{
    throw new TimeoutException("Init too long");
}
此外,我的支票也是异步的,它的工作原理就像一个符咒:)

public async Task performrpcall(字符串名,参数对象[]PAR)
{
//等待cde上的初始化。。。
//准备通话。。。
//产生
产品产量(call);
//等待回答
return wait_inputpanswers statements.Take();
}
我想我应该使用另一种方法来启动这个无限循环,但是我已经有了异步任务方法——所以我真的不知道该怎么做。
有什么帮助吗?

好的,在大量阅读(没有找到)和@svick的建议后,我决定调用此方法,而不将“等待”作为单独的任务。运行。 Aso我决定在ThreadPool中运行它

我的最终代码是:

try
{                                   
    /*await Task.WhenAny(SendStatementsAsync(_cts.Token), 
           ReadTcpClientAsync(_cts.Token),
           ProcessUpdateAsync(_cts.Token, _progress)).ConfigureAwait(false);*/
    Task.Run(() => SendStatementsAsync(_cts.Token)).ConfigureAwait(false);
    Task.Run(() => ReadTcpClientAsync(_cts.Token)).ConfigureAwait(false);
    Task.Run(() => ProcessUpdateAsync(_cts.Token, _progress)).ConfigureAwait(false);
    Trace.WriteLineIf(clientSwitch.TraceInfo, "Worker threads started", "[Client.RunAsync]");
}
一切正常。。 我不确定它在异常处理中会导致什么问题,因为我知道它们会丢失

当然,这样的电话会发出警告

由于不等待此调用,因此当前方法的执行 在呼叫完成之前继续。考虑应用“等待” 接线员呼叫呼叫结果

这很容易被抑制

// just save task into variable
var send = Task.Run(() => SendStatementsAsync(_cts.Token)).ConfigureAwait(false); 

另外,如果有人知道更好的解决方案,我会很高兴听到它。

看看blockingcollection只是不要等待
RunAsync()
?@Blam我有自己的IProducerConsumer实现,它工作得很好,我不需要另一个。@s点击我所做的。但在IL中等待RunAsync将创建ContinueWith构造,其中RunAsync后面一行的所有语句都将是ContinueWith。所以它们永远不会被执行,因为RunAsync什么时候都不会触发(除了取消,但它是无关的)我的意思是,您应该尝试调用
RunAsync()
,但不调用
wait
(假设您可以忽略它引发的任何异常)。
// just save task into variable
var send = Task.Run(() => SendStatementsAsync(_cts.Token)).ConfigureAwait(false);