Я хочу передать исключение из текущего потока (что поток не является основным потоком) к основному потоку. Почему? Поскольку я проверяю, что мои твердые привязывают другой поток (что таймер использования потока для проверки), и когда HardLock
не доступно или недопустим, я создаю исключение, которое определяется один, и затем выдайте то исключение.
Так, чтобы исключение не работало хорошо.;(
Лучше всего заменить Thread
на Task
(новый в .NET 4.0). Класс Task
обрабатывает надлежащее маршалинг исключения для любого потока, проверяющего результат выполнения задачи.
Если использование .NET 4.0 невозможно, то CoreEx.dll из Rx extensions включает метод расширения Exception.PrepareForRethrow
, который сохраняет стек вызовов для исключений. Вы можете использовать его в сочетании с предложенным MaLio SynchronizationContext
для передачи исключения другому потоку.
Не зная ничего другого, похоже, что ваша блокировка сломана, если вам нужен поток, чтобы гарантировать, что ваши блокировки не удерживаются слишком долго или недействительны.
Если вам действительно нужно генерировать исключения в основном потоке, настройте очередь связи от всех ваших «рабочих потоков» до «главного потока» и оберните все рабочие потоки в обработчик исключений, который не делает ничего, кроме добавления исключения из очереди, а затем убивает этот поток. Ваш главный поток может опросить очередь, чтобы обнаружить исключения и перезапустить потоки, которые умерли после исправления состояния ошибки.
Передайте ссылку на контекст выполнения основной формы в поток (через делегата или поле). Затем вызовите метод (отправить или отправить) через этот контекст синхронизации из вашего потока, который вызывает исключение. Контекст выполнения гарантирует, что он будет обработан потоком пользовательского интерфейса.
Только мои 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();
Возможно, вам будет проще держать обработку исключений внутри потока и передавать обратно сообщение об исключении и трассировку стека, возвращая MyException.ToString()
в обратном вызове. Когда я получаю исключения из другого потока, все, что я ищу, находится в этой строке.
Вы можете использовать исключение как параметр в событии.
И обработайте это после отправки исключения в другой поток.
Пример кода.
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;
}