繁体   English   中英

使用回调将多个任务排队

[英]Queue several tasks with callback

假设我们有一些方法可以完成很多工作。

最初,我们不知道有多少种方法(可以是1,可以是10)。

在代码中,如下所示:

public interface IWorker
{
    void DoWork(DataContainer data);
}

还有几个实现此接口的类。 然后我们有实例列表。

List<IWorker> workers = new List<IWorker>();

我想异步运行这些方法。 另外,当它们全部执行后,我需要一些回调。

public void Callback()
{
    Console.WriteLine("everything done");
}

有没有一种方法可以在不编写自定义包装的情况下进行? 使用ThreadPool,可以并行执行任务吗?

据我所知,Parrallel阻塞线程直到任务完成,所以这不是首选行为。

如我所见,在创建Task时,应该有没有参数的方法,所以这也不是一件好事。

在ThreadPool中,可以使用QueueUserWorkItem方法,但是使用此方法,我将不会获得单个“总计完成”回调。

当然,我可以制作自己的包装器,以使用ThreadPool实现所需的功能,但目标是无需编写此类包装器即可。

有人可以帮忙吗? 谢谢。

您正在寻找TPL和Task类。

为每个操作创建一个Task ,然后调用Task.WhenAll以获取聚合任务

您正在寻找Task.WhenAll。 创建一堆执行所需任务的任务,然后等待所有任务并继续执行回调。 我拆分了DoWork方法的异步版本-如果您总是要异步调用它,则不一定需要这样做。

public interface IWorker
{
    Task DoWorkAsync(string data);
    void DoWork(string data);
}

public class Worker : IWorker
{
    public Task DoWorkAsync(string data)
    {
        return Task.Run(() => DoWork(data));
    }

    public void DoWork(string data)
    {
        Console.WriteLine(data);
        Thread.Sleep(100);
    }
}

public class Runner
{
    public void Callback()
    {
        Console.WriteLine("Everything done");
    }

    public void Run()
    {
        var workers = new List<IWorker> {new Worker(), new Worker(), new Worker()};
        var tasks = workers.Select(t => t.DoWorkAsync("some data"));

        Task.WhenAll(tasks).ContinueWith(task => Callback());

        Console.WriteLine("Waiting");
    }
}

听起来像是CountdownEvent类的主要候选人:

List<IWorker> workers = new List<IWorker>();
using (CountdownEvent e = new CountdownEvent(workers.Count))
{
    foreach (IWorker worker in workers)
    {
        // Dynamically increment signal count.
        e.AddCount();
        // run work itself on another thread
        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            try
            {
                ((IWorker)state[0]).DoWork((DataContainer)state[1]);
            }
            finally
            {
                e.Signal();
            }
        },
        // pass required parameters for block of work
        new object[] { worker, dataForWorker });
    }

    // wait for all workers to finish
    e.Wait();
    // run callback code
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM