Automapper/StructureMap issues with TPL version of

2019-08-09 12:57发布

This is my synchronous working version for some workers to do some different work given a generic workload:

foreach (var worker in _workers)
{
    worker.DoWork(workload);
}

I am trying to exploit existing cores via the task parallel library (TPL) using this:

foreach (var worker in _workers)
{
    var worker1 = worker;
    await Task.Run(() => worker1.DoWork(workload));
}
await Task.WhenAll();

The intention is, that each worker is executed in its own thread. Please note that this runs in a async method, which receives a 'workload' from time to time. I want to ensure that all work is done before the foreach is run again. Hence, the line:

await Task.WhenAll();  

Unfortunately I seem to have some sporadic mapping exception related to automapper/structuremap (it works fine synchronously). This is my structuremap code:

public class MyRegistry : Registry
{
    public MyRegistry()
    {
        For<ISomething>().Singleton().Use<SomethingConcrete>();

        var profiles =
        from t in typeof(MyRegistry).Assembly.GetTypes()
        where typeof(Profile).IsAssignableFrom(t)
        select (Profile)Activator.CreateInstance(t);

        var config = new MapperConfiguration(cfg =>
        {
        foreach (var profile in profiles)
        {
            cfg.AddProfile(profile);
        }
        });

        For<MapperConfiguration>().Use(config);
        For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));
    }
}

To isolate the problem, is there something fundamentally wrong with the TPL code to start with?

1条回答
在下西门庆
2楼-- · 2019-08-09 13:18

Is there something fundamentally wrong with the TPL code?

Yes. await Task.WhenAll() doesn't do anything as it's supposed to accept tasks as parameters. And offloading to the ThreadPool with Task.Run but awaiting each task sequentially doesn't either.

What you probably wanted to do is this:

var tasks = new List<Task>();
foreach (var worker in _workers)
{
    tasks.Add(Task.Run(() => worker.DoWork(workload)));
}

await Task.WhenAll(tasks);

Or more simply this:

await Task.WhenAll(_workers.Select(worker => Task.Run(() => worker .DoWork(workload)));

Which creates a task for each worker that will run on the ThreadPool and then uses Task.WhenAll to await the completion of all these tasks.

查看更多
登录 后发表回答