Отправка исключения от потока до основного потока?

Я хочу передать исключение из текущего потока (что поток не является основным потоком) к основному потоку. Почему? Поскольку я проверяю, что мои твердые привязывают другой поток (что таймер использования потока для проверки), и когда HardLock не доступно или недопустим, я создаю исключение, которое определяется один, и затем выдайте то исключение.
Так, чтобы исключение не работало хорошо.;(

14
задан Ed Power 13 November 2015 в 19:59
поделиться

6 ответов

Лучше всего заменить Thread на Task (новый в .NET 4.0). Класс Task обрабатывает надлежащее маршалинг исключения для любого потока, проверяющего результат выполнения задачи.

Если использование .NET 4.0 невозможно, то CoreEx.dll из Rx extensions включает метод расширения Exception.PrepareForRethrow, который сохраняет стек вызовов для исключений. Вы можете использовать его в сочетании с предложенным MaLio SynchronizationContext для передачи исключения другому потоку.

13
ответ дан 1 December 2019 в 10:17
поделиться

Не зная ничего другого, похоже, что ваша блокировка сломана, если вам нужен поток, чтобы гарантировать, что ваши блокировки не удерживаются слишком долго или недействительны.

Если вам действительно нужно генерировать исключения в основном потоке, настройте очередь связи от всех ваших «рабочих потоков» до «главного потока» и оберните все рабочие потоки в обработчик исключений, который не делает ничего, кроме добавления исключения из очереди, а затем убивает этот поток. Ваш главный поток может опросить очередь, чтобы обнаружить исключения и перезапустить потоки, которые умерли после исправления состояния ошибки.

3
ответ дан 1 December 2019 в 10:17
поделиться

Передайте ссылку на контекст выполнения основной формы в поток (через делегата или поле). Затем вызовите метод (отправить или отправить) через этот контекст синхронизации из вашего потока, который вызывает исключение. Контекст выполнения гарантирует, что он будет обработан потоком пользовательского интерфейса.

2
ответ дан 1 December 2019 в 10:17
поделиться

Только мои 2 цента.

Я думаю, что вы можете использовать Invoke, BeginInvoke в основной форме, если вы используете Windows Forms, чтобы отправить туда исключение из блока try / catch. Или вы можете создать обработчик / делегат событий в основном потоке и отправлять исключения через него в основной поток, чтобы метод в основном потоке мог его обработать. Если честно, не пробовал этих решений, но это мои первые идеи.

PS. Возможно, создание WorkerQueue в основном потоке также является вариантом. Он будет работать как backgroundWorker, и когда он получит новое исключение, отправленное в нем, он обработает его соответствующим образом ... Я могу привести вам небольшие примеры, если вам интересно.

Изменить:

public class JobQueue
{
    private Queue<Exception> pendingJobs = new Queue<Exception>();
    private Exception defaultJob = null;

    bool run = true;

    public void AddJob(Exception job)
    {
        pendingJobs.Enqueue(job);
    }

    public JobQueue()
    {
        defaultJob=null;
    }

    public void StopJobQueue()
    {
        run = false;
    }


    public void Run()
    {
        while (run)
        {

                Exception job = (pendingJobs.Count > 0) ? pendingJobs.Dequeue() : defaultJob;

                if (job!= null)
                {
                  ////what to do with current Exception
                 }

            Thread.Sleep(20); //I know this is bad...
        }


        pendingJobs.Clear();
    }



}
}

Чтобы использовать: В классе основного потока:

    private JobQueue m_jobQueue;

В Initialize () или там, где начинается основной поток:

   Backgroundworker bw = new Backgroundworker();
   bw.DoWork+= jobQueue.Run;
   bw.StartAsync();
    //m_jobQueue = new JobQueue();
    //    new Thread(new ThreadStart(jobQueue.Run)).Start(); 

И для отправки исключения используйте:

   m_jobQueue.AddJob(StackOverflowException);

Остановить:

    m_jobQueue.StopJobQueue();
2
ответ дан 1 December 2019 в 10:17
поделиться

Возможно, вам будет проще держать обработку исключений внутри потока и передавать обратно сообщение об исключении и трассировку стека, возвращая MyException.ToString() в обратном вызове. Когда я получаю исключения из другого потока, все, что я ищу, находится в этой строке.

2
ответ дан 1 December 2019 в 10:17
поделиться

Вы можете использовать исключение как параметр в событии.
И обработайте это после отправки исключения в другой поток.
Пример кода.

public delegate void SendToMainDel(string threadName,Exception ex);
public event SendToMainDel SendToMainEv;

public void MySecondThread()
{
    try
    {
    ....
    }catch(Exception ex)
    {
         if(SendToMainEv!=null)
            SendToMainEv("MySecondThread",ex);
    }
}

...
    SendToMainEv += ReceiveOtherThreadExceptions;
...

public void ReceiveOtherThreadExceptions(string threadName,Exception ex)
{ 
   if(InvokeRequired)
   {
      BeginInvoke(new SendToMainDel(ReceiveOtherThreadExceptions), threadName, ex);
      return;
   }

   //there you can handle the exception
   //throw ex;
}
4
ответ дан 1 December 2019 в 10:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: