Я разрабатываю приложение Android-мессенджера на основе xamarin и .net 5 async/ждет.Запуск нескольких бесконечных циклов с асинхронным/ожиданием
В моем приложении у меня есть шаблон производителя/потребителя для обработки сообщений, которые производятся на бесконечных циклах.
, например ReadTcpClientAsync производителя:
async Task ReadTcpClientAsync(CancellationToken cancellationToken)
{
cde.Signal();
while (!cancellationToken.IsCancellationRequested)
{
byte[] buffer = await atc.ReadAsync(cancellationToken);
// queue message...
}
}
или SendStatementsAsync потребителя, который DEQUE сообщений и ожидает 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();
это строительно-монтажных работ довольно хорошо на тестах, но есть один метод wh потому что я думаю, что совершил огромную ошибку. Этот метод предназначен для запуска всего клиентского бэкэнд, начиная с 3 pro/con while (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)
{
}
}
Забудьте о андроида на данный момент, думаю, любой пользовательский интерфейс (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, потому что он никогда не вернется из Task.WhenAny (...). И мне нужно выполнить проверку состояния, но мне нужно это про/минусы методы, созданные, потому что мой чек ждать на ManualResetEvent для него:
if (!cde.Wait(15000))
{
throw new TimeoutException("Init too long");
}
Кроме того, мой чек асинхронной тоже, и он работает как шарм :)
public async Task<TLCombinatorInstance> PerformRpcCall(string combinatorName, params object[] pars)
{
// wait for init on cde ...
// prepare call ...
// Produce
ProduceOutput(call);
// wait for answer
return await _inputRpcAnswersStatements.Take();
}
Я думаю, что я должен использовать другой подход для запуска этой бесконечной петли, но я уже ASync Методы ЗАДАЧИ всего пути - так что я действительно не знаю, что делать. Любая помощь, пожалуйста?
Посмотрите на BlockingCollection – Paparazzi
Просто не 'await'' RunAsync()'? – svick
@Blam У меня есть собственная реализация IProducerConsumer, и он работает очень хорошо, мне не нужен другой. – xakz