最佳的异步而方法 [英] Best asynchronous while method

查看:196
本文介绍了最佳的异步而方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写一些异步code,基本上试图多次交谈,并初始化数据库。很多时候第一次尝试失败,因此要求它重试。

I need to write some asynchronous code that essentially attempts to repeatedly talk to and initialise a database. Quite often the first attempt will fail hence the requirement for it to retry.

在旧的日子里,我会用类似的模式:

In days of old I would have used a pattern similar to:

void WaitForItToWork()
{
    bool succeeded = false;
    while (!succeeded)
    {
        // do work
        succeeded = outcome; // if it worked, make as succeeded, else retry
        Threading.Thread.Sleep(1000); // arbitrary sleep
    }
}

我认识了很多变化已经作出近期到.NET的问候异步模式,所以我的问题其实就是用这个是最好的方法还是值得探索异步的东西,如果是的话我怎么实现这个模式在异步

I realise a lot of changes have been made recently to .NET with regards to async patterns so my question really is this the best method to use or is it worth while exploring the async stuff and if so how do I implement this pattern in async?

更新

只是为了澄清,我希望异步产卵这项工作,这样它会生成它不必等待它完成,因为它会在服务的构造函数来催生这样的构造函数必须立刻返回方法。

Just to clarify, I want to spawn this work asynchronously so that the method which spawns it does not have to wait for it to finish as it will be spawned in the constructor of a service so the constructor must return instantly.

推荐答案

您可以重构该片段是这样的:

You could refactor that fragment like this:

async Task<bool> WaitForItToWork()
{
    bool succeeded = false;
    while (!succeeded)
    {
        // do work
        succeeded = outcome; // if it worked, make as succeeded, else retry
        await Task.Delay(1000); // arbitrary delay
    }
    return succeeded;
}

显然,不仅有利于它会给你是更有效地使用线程池,因为它不总是需要整个线程使延迟发生

Apparently, the only benefit it would give you is more efficient use of thread pool, because it doesn't always take a whole thread to make the delay happen.

根据您如何获取结果,可能会有更有效的方式来得到这个工作做好使用异步/计谋。通常情况下,你可能有一些像 GetOutcomeAsync()这将使Web服务,数据库或插座异步调用以自然的方式,所以你只是做 VAR的结果=等待GetOutcomeAsync()

Depending on how you obtain outcome, there may be much more efficient ways to get this job done using async/await. Often you may have something like GetOutcomeAsync() which would make a web service, database or socket call asynchronously in a natural way, so you'd just do var outcome = await GetOutcomeAsync().

要考虑到 WaitForItToWork 将被分成部分由编译器和部分来自等待行是很重要将异步方式继续执行。 这里也许在它是如何在内部做了最好的解释。问题是,通常在某些时候你的$ C $了C你需要在异步任务的结果同步。例如:

It's important to take into account that WaitForItToWork will be split into parts by compiler and the part from await line will be continued asynchronously. Here's perhaps the best explanation on how it's done internally. The thing is, usually at some point of your code you'd need to synchronize on the result of the async task. E.g.:

private void Form1_Load(object sender, EventArgs e)
{
    Task<bool> task = WaitForItToWork();
    task.ContinueWith(_ => {
        MessageBox.Show("WaitForItToWork done:" + task.Result.toString()); // true or false
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

您可以简单做到了这一点:

You could have simply done this:

private async void Form1_Load(object sender, EventArgs e)
{
    bool result = await WaitForItToWork();
    MessageBox.Show("WaitForItToWork done:" + result.toString()); // true or false
}

这将然而让 Form1_Load的异步方法了。

That would however make Form1_Load an async method too.

[更新]

下面是我试图来说明异步/计谋实际上没有这种情况。我创建了两个版本的相同的逻辑, WaitForItToWorkAsync (使用异步/计谋)和 WaitForItToWorkAsyncTap (使用< A HREF =htt​​p://msdn.microsoft.com/en-us/library/hh873175.aspx> TAP模式的无异步/计谋)。弗里斯特的版本是很微不足道的,不同的是第二个。因此,虽然异步/计谋主要是编译器的语法糖,它使异步code更容易编写和理解。<​​/ P>

Below is my attempt to to illustrate what async/await actually does in this case. I created two versions of the same logic, WaitForItToWorkAsync (using async/await) and WaitForItToWorkAsyncTap (using TAP pattern without async/await). The frist version is quite trivial, unlike the second one. Thus, while async/await is largely the compiler's syntactic sugar, it makes asynchronous code much easier to write and understand.

// fake outcome() method for testing
bool outcome() { return new Random().Next(0, 99) > 50; }

// with async/await
async Task<bool> WaitForItToWorkAsync()
{
    var succeeded = false;
    while (!succeeded)
    {
        succeeded = outcome(); // if it worked, make as succeeded, else retry
        await Task.Delay(1000);
    }
    return succeeded;
}

// without async/await
Task<bool> WaitForItToWorkAsyncTap()
{
    var context = TaskScheduler.FromCurrentSynchronizationContext();
    var tcs = new TaskCompletionSource<bool>();
    var succeeded = false;
    Action closure = null;

    closure = delegate
    {
        succeeded = outcome(); // if it worked, make as succeeded, else retry
        Task.Delay(1000).ContinueWith(delegate
        {
            if (succeeded)
                tcs.SetResult(succeeded);
            else
                closure();
        }, context);
    };

    // start the task logic synchronously
    // it could end synchronously too! (e.g, if we used 'Task.Delay(0)')
    closure();

    return tcs.Task;
}

// start both tasks and handle the completion of each asynchronously
private void StartWaitForItToWork()
{
    WaitForItToWorkAsync().ContinueWith((t) =>
    {
        MessageBox.Show("WaitForItToWorkAsync complete: " + t.Result.ToString());
    }, TaskScheduler.FromCurrentSynchronizationContext());

    WaitForItToWorkAsyncTap().ContinueWith((t) =>
    {
        MessageBox.Show("WaitForItToWorkAsyncTap complete: " + t.Result.ToString());
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

// await for each tasks (StartWaitForItToWorkAsync itself is async)
private async Task StartWaitForItToWorkAsync()
{
    bool result = await WaitForItToWorkAsync();
    MessageBox.Show("WaitForItToWorkAsync complete: " + result.ToString());

    result = await WaitForItToWorkAsyncTap();
    MessageBox.Show("WaitForItToWorkAsyncTap complete: " + result.ToString());
}

几句话线程。这里有明确创建没有额外的线程。在内部, Task.Delay()的实施可能会使用池中的线程(我怀疑他们使用的Timer队列的),但在这个特殊的例子(WinForms应用程序),后继续等待会发生相同的UI线程。在其他执行环境(例如,一个控制台应用程序),它可能会继续在不同的线程。 IMO,由斯蒂芬·克利这篇文章是必须看的懂异步/计谋线程的概念。

A few words on threading. There is no additional threads explicitly created here. Internally, Task.Delay() implementation may use pool threads (I suspect they use Timer Queues), but in this particular example (a WinForms app), the continuation after await will happen on the same UI thread. In other execution environments (e.g. a console app), it might continue on a different thread. IMO, this article by Stephen Cleary is a must-read to understand async/await threading concepts.

这篇关于最佳的异步而方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆