How to switch between async & sync in .NET/C#

若如初见. 提交于 2019-12-23 15:55:30

问题


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.

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...

Each GetX() method signature is like so:

public async Task<ProcessWithResult> GetChildType1Entities()

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


回答1:


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

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.



来源:https://stackoverflow.com/questions/32587640/how-to-switch-between-async-sync-in-net-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!