如何在异步与amp;之间切换在.NET/C#中同步 [英] How to switch between async & sync in .NET/C#

查看:31
本文介绍了如何在异步与amp;之间切换在.NET/C#中同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在C#中对多个任务进行异步/同步处理之间进行切换?

How do I go about switching between async/sync processing of multiple tasks in C#?

我希望能够在并行和同步处理任务之间进行切换,以进行测试/分析.

I'd like to be able to switch between parallel and synchronous processing of tasks for testing/profiling purposes.

最初,我有一系列内联初始化的任务.虽然这对于并行来说很好,但是我发现我的同步代码不起作用,因为每种方法都会在数组初始化时被激活.

Initially I had an array of Tasks initialised inline. While this was fine for parallel, I found my synchronous code wouldn't work because each method would be activated on initialization of the array.

我决定改用Lazy.此代码正确吗?如果没有,如何最好地实现?

I decided to try Lazy instead. Is this code correct? If not, how is this best achieved?

  var runTasks = new Lazy<Task<ProcessWithResult>>[]
            {
                new Lazy<Task<ProcessWithResult>>(() => GetHeaderRecord()),
                new Lazy<Task<ProcessWithResult>>(() => GetChildType1Entities()),
                new Lazy<Task<ProcessWithResult>>(() => GetChildType2Entities()),
                new Lazy<Task<ProcessWithResult>>(() => GetChildType3Entities()),                     
            };

            if (Settings.Default.AsyncProcessing)
            {
                Task.WaitAll(runTasks.Select(x => x.Value).ToArray());
            }
            else
            {
                // do these in sequence
                runTasks.ToList().ForEach(t => t.Value.Wait());
            }

            // carryon...

每个GetX()方法签名如下:

Each GetX() method signature is like so:

public async Task<ProcessWithResult> GetChildType1Entities()

对数据库或文件I/O至少执行一次异步操作.

With at least one async operation on Database or file i/o.

推荐答案

您的方法可行,但是我会避免使用Lazy.

Your approach could work, however i would avoid using Lazy for this.

C#中已经有一个懒惰的语言构造,它的收益回报率高,并且代码更简洁:

There is a lazy language construct in C# already, it's yield return, and it would result in cleaner code:

public static class Runner
{
    public static async Task<IEnumerable<ProcessWithResult>> RunAll(this IEnumerable<Task<ProcessWithResult>> tasks, bool runSequentially)
    {
        if (!runSequentially) return await Task.WhenAll(tasks);
        var results = new List<ProcessWithResult>();
        foreach (var task in tasks)
            results.Add(await task);
        return results;
    }
}

public class Tests
{
    [Test]
    public void RunInParallel()
    {
        var results = GetAllTasks().RunAll(false).Result;
        CollectionAssert.AreEqual(new[] { 2, 1 }, results.OrderBy(r => r.WhenFinished).Select(r => r.Id));
    }

    [Test]
    public void RunInSequentially()
    {
        var results = GetAllTasks().RunAll(true).Result;
        CollectionAssert.AreEqual(new[] { 1, 2 }, results.OrderBy(r => r.WhenFinished).Select(r => r.Id));
    }

    IEnumerable<Task<ProcessWithResult>> GetAllTasks()
    {
        yield return RunTask(1, 1000);
        yield return RunTask(2, 100);
    }

    async Task<ProcessWithResult> RunTask(int id, int wait)
    {
        await Task.Delay(wait);
        return new ProcessWithResult {Id = id, WhenFinished = DateTime.Now};
    }
}

public class ProcessWithResult
{
    public int Id { get; set; }
    public DateTime WhenFinished { get; set; }
}

通过这种方法,该方法在生产和测试中仍然可以异步运行.

This way the method still runs asyncronously both in production and the tests.

这篇关于如何在异步与amp;之间切换在.NET/C#中同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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