缓冲任务数据超时

时间:2016-06-03 17:44:05

标签: c# .net multithreading rabbitmq task-parallel-library

我有一个相当棘手的问题需要解决。我有多个(最多一百个或更多)任务,每个任务都产生一个数据,比如字符串。这些任务可以在每个时刻产生,并且一次可以有大量的任务而在另一个时间没有。每项任务都必须收到bool,表明是否正确完成(非常重要)。

我想实现某种缓冲区,从任务中收集数据并将其刷新到外部服务,返回操作状态(ok或fail)。此外,我的缓冲区必须通过超时刷新(以防止等待新任务生成数据太长时间)。

到目前为止,我试图制作一些共享的项目清单。任务可以将项目添加到列表中,还有另一项任务,检查列表中的计时器或项目计数并刷新它们。但是在这种方法中,我无法告诉任务刷新操作的状态,这对我来说非常糟糕。

我会感激任何解决我问题的方法。

1 个答案:

答案 0 :(得分:1)

据我了解,您需要将每项任务的结果保存到数据库/服务中,但您不希望立即执行此操作。

你的问题可能有不止一个解决方案,但很难找到最好的解决方案,所以我将描述我将如何做到这一点......很快。

您需要保存/发送的数据的容器。

public class TaskResultEventArgs : EventArgs
{
    public bool Result { get; set; }
}

也为您执行任务的通知程序。我以为你可以推迟执行任务。

public class NotifyingTaskRunner
{
    public event EventHandler<TaskResultEventArgs> TaskCompleted;

    public void RunAndNotify(Task<bool> task)
    {
        task.ContinueWith(t =>
        {
            OnTaskCompleted(this, new TaskResultEventArgs { Result = t.Result });
        }, TaskContinuationOptions.OnlyOnRanToCompletion);
        task.Start();
    }

    protected virtual void OnTaskCompleted(object sender, TaskResultEventArgs e)
    {
        var h = TaskCompleted;
        if (h != null)
        {
            h.Invoke(sender, e);
        }
    }
}

可以缓冲和/或刷新结果的侦听器(或者您可能希望将其委托给另一个类)。

public class Listener
{
    private ConcurrentQueue<bool> _queue = new ConcurrentQueue<bool>();

    public Listener(NotifyingTaskRunner runner)
    {
        runner.TaskCompleted += Flush;
    }

    public async void Flush(object sender, TaskResultEventArgs e)
    {
        // Enqueue status to flush everything later (or flush it immediately)
        _queue.Enqueue(e.Result);
    }
}

这就是你可以一起使用所有东西的方法。

var runner = new NotifyingTaskRunner();
var listener = new Listener(runner);

var t1 = new Task<bool>(() => { return true; });
var t2 = new Task<bool>(() => { return false; });

runner.RunAndNotify(t1);
runner.RunAndNotify(t2);