Асинхронная многопоточная обработка исключений? - PullRequest
6 голосов
/ 30 августа 2009

Я хочу использовать подход обработки исключений в моем асинхронном программировании (beginInvoke / endInvoke), при котором в случае сбоя одного из потоков (beginInvoke) я хочу, чтобы все остальные потоки асинхронной обработки перестали работать. Пожалуйста, предложите какое-нибудь решение ?, ниже я также прилагаю свой пример кода:

public List<ThreadResultDto> SendMailAsynch(List<ThreadRequestDto>  requestDto)
{
    List<ThreadResultDto> resultDto = new List<ThreadResultDto>();
    List<IAsyncResult> asyncResults = new List<IAsyncResult>();

    foreach (ThreadRequestDto t in requestDto)
    {
        //Create a delegate.
        DoSomeAsynchWorkDelegate del = new DoSomeAsynchWorkDelegate(DoSomeAsynchWork);
        // Initiate the asynchronous call
        IAsyncResult a = del.BeginInvoke(t,null, del);
        //IAsyncResult a = del.BeginInvoke(t, null,null);
        asyncResults.Add(a);
    }

    foreach (IAsyncResult ar in asyncResults)
    {
        // wait for each one to complete, then call EndInvoke, passing in the IAsyncResult.
        // We cast ar.AsyncState to a DoSomeAsynchWorkDelegate, as we passed it in as the second parameter to BeginInvoke. 
        ar.AsyncWaitHandle.WaitOne();

        //AsyncState property of IAsyncResult is used to get the delegate that was used to call that method
        DoSomeAsynchWorkDelegate del = (DoSomeAsynchWorkDelegate)ar.AsyncState;

        // Call EndInvoke to get the result.  Add the result to the list of items. 
        resultDto.Add(del.EndInvoke(ar));
    }

    return resultDto;
}

1 Ответ

2 голосов
/ 08 декабря 2009

Лучшим способом, вероятно, является использование общего ManualResetEvent .

Например:

class MyClass
{
    private ManualResetEvent workFailedEvent = new ManualResetEvent(false);

    public List<ThreadResultDto> SendMailAsynch(List<ThreadRequestDto>  requestDto)
    {
        workFailedEvent.Reset();

        // --- The rest of your code as written in your post ---
    }

    private void DoAsyncWorkFirst()
    {
        try
        {
            for (int i = 0; i < 10000; i++)
            {
                if (workFailedEvent.WaitOne(0, true))
                {
                    break;
                }

                // -- Do some work here ---
            }
        }
        catch (MyException)
        {
            workFailedEvent.Set();
        }
    }

    private void DoAsyncWorkSecond()
    {
        try
        {
            for (int j = 0; j < 20000; j++)
            {
                if (workFailedEvent.WaitOne(0, true))
                {
                    break;
                }
                // --- Do some different work here ---
            }
        }
        catch (MyOtherException)
        {
            workFailedEvent.Set();
        }
    }
}

Интересной частью здесь является вызов WaitOne (0, true) . Если вы используете тайм-аут 0, поток не будет блокироваться. Поскольку ManualResetEvent синхронизируется операционной системой, этот конкретный вызов метода является удобным способом проверки сигнала без необходимости беспокоиться о состоянии гонки или реализовать собственную блокировку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...