0
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 を使用しています。

Add() メソッドは、API ユーザーによって呼び出されます。上記の例では、void work() メソッド内で例外をキャッチし、そこにログを記録しています。

しかし、その代わりに、例外をキャッチしてユーザーに再スローしたいと考えています。while ループ内で実行される永久スレッドである Sametime は、キュー内の次のタスクに進むことによって、例外から回復する必要があります。私の短い質問は - void work() 内で発生する例外をどのようにスローするのですか?それでも、キュー内の次のタスクのために消費者は生き続けます。

4

3 に答える 3

1

コンシューマー スレッドとメイン スレッドの間で何らかの通信を確立する必要があります。コンシューマーが例外に遭遇すると、メイン スレッドに通知し、次のタスクに進む必要があります。

Winforms を使用しているため、メイン スレッドに通知する最も簡単な方法は を使用することInvokeです。例については、次の質問を参照してください。

于 2013-06-23T08:36:15.970 に答える
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);
}

これが役立つことを願っています。

于 2013-06-23T08:00:07.537 に答える
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);
            }
        }
    }
}
于 2013-06-27T06:09:20.547 に答える