public class ProducerConsumerQueue
{
public void EnqueueTask(MyTask task)
{
}
void Work()
{
while (true)
{
try
{
// my task goes here
Thread.Sleep(2000);
}
catch(Exception ex)
{
Log(ex);
}
}
}
}
制片:
public void Add()
{
MyTask task = new MyTask();
new ProducerConsumerQueue().EnqueueTask(task);
}
我在.NET 3.5中。
我的API用户将调用Add()方法。在上面的例子中,在方法内部,void work(),我正在捕获异常并记录在那里。
但不是那样,我想抓住并重新抛出用户的异常。 Sametime是在while循环内运行的永久线程,应该通过继续执行队列中的下一个任务从异常中恢复。我的简短问题是 - 如何抛出void work()中发生的异常,但仍然消费者为队列中的下一个任务保持活跃状态。
答案 0 :(得分:1)
继续我们对评论的讨论,你可能会做一些事情,比如收集执行任务队列时发生的所有异常(但是你需要在循环上执行队列),然后把它扔回调用者。 如下所示:
public void ExecuteAllTasks()
{
var exceptions = new List<Exception>();
IEnumerable<MyTask> tasks = GetQueuedTasks(); // get all tasks (or possibly pass them to the method) ...
foreach (MyTask task in tasks)
{
try
{
// execute your tasks here ...
}
catch (Exception ex)
{
// collect all the exceptions
exceptions.Add(ex);
}
}
// throw all the errors at once
if (exceptions.Any())
throw new AggregateException(_exceptions);
}
我希望这会有所帮助。
答案 1 :(得分:1)
您需要在消费者线程和主线程之间建立某种通信。当消费者遇到异常时,它应该通知主线程并继续下一个任务。
由于您使用的是Winforms,因此通知主线程的最简单方法是使用Invoke
。有关示例,请参阅following question。
答案 2 :(得分:0)
介绍在任务完成时调用的回调:
public interface ICompletionState
{
public ITask Task { get; set; }
public Exception Exception { get; set; }
}
public class CompletionState : ICompletionState
{
public ITask Task { get; set; }
public Exception Exception { get; set; }
public Action<ICompletionState> Callback { get; set; }
}
public class ProducerConsumerQueue
{
ConcurrentQueue<CompletionState> _tasks = new ConcurrentQueue<CompletionState>();
public void EnqueueTask(ITask task, Action<ICompletionState> callback)
{
_tasks.Enqueue(new CompletionState{ Task = task, Callback = callback });
}
void Work()
{
while (true)
{
CompletionState cs;
try
{
if (!_tasks.TryDequeue(out cs))
continue;
cs.Task.Execute();
cs.Callback(cs);
}
catch(Exception ex)
{
cs.Exception = ex;
cs.Callback(cs);
}
}
}
}