7

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

void dispatcherTimer_Tick(object sender, EventArgs e) 
{ 
    string srUrl = lstLocalIndex[irLocalIndex] + lstMainIndex[irMainIndex].Replace("0;",""); 

    Task.Factory.StartNew(() => 
    { 
     startNewWindow(srUrl); 
    }); 

} 


    void startNewWindow(string srUrl) 
{ 
    NewWindowThread<TitleWindow, string>(c => new TitleWindow(c), srUrl); 
} 

Теперь этот код является причиной ошибки. Я также приложу Скриншот

 private void NewWindowThread<T, P>(Func<P, T> constructor, P param) where T : Window 
    { 
     Thread thread = new Thread(() => 
     { 
      T w = constructor(param); 
      w.Show(); 
      w.Closed += (sender, e) => w.Dispatcher.InvokeShutdown(); 
      try 
      { 
       System.Windows.Threading.Dispatcher.Run(); 
      } 
      catch 
      { 

      } 
     }); 
     thread.SetApartmentState(ApartmentState.STA); 
     try 
     { 
      thread.Start(); 
     } 
     catch 
     { 

     } 
    } 

Эта ошибка вызывает целую ошибку программного обеспечения бросить и перестать работать, даже если я буду называть их в новом потоке :(

Эта линия метания ошибку System.Windows.Threading.Dispatcher. Run();

Пожалуйста, проверьте также скриншот

enter image description here

C# 4.0 WPF

+0

Вы фактически используете * два * потока, один в «Задаче», а затем в «Thread», лучше просто поместить код, который вы хотите запустить, в качестве кода запуска в «Thread». – casperOne

+0

@casperOne Я также пробовал, что все еще сбой приложения. И это происходит через некоторое время не сразу. Он работает как 30 минут, затем сбой. Время сбоя меняется. – MonsterMMORPG

+0

Нет, говорят, что ваша память сломана. Это должно быть так! (btw - это самое тупая ошибка, с которой я столкнулся после «неопределенной ошибки»). – leppie

ответ

0

Вы используете функцию лямбда как функцию потока. Эта лямбда называется новой нитью. На этапе поток фактически создан, он будет искать аргумент, который вы предоставляете, который является локальной переменной srUrl, но к тому времени, когда это произойдет, ваша функция (dispatcherTimer_Tick) уже вышла, поэтому srUrl будет находиться в составе стек, который больше не определяется должным образом (следовательно, нарушение прав доступа). Легкое исправление заключается в том, чтобы определить переменную в классе и быстро добавить srLoc. Более правильным решением является фактически передать srLoc в качестве аргумента:

() => 
{ 
    startNewWindow(srUrl); 
} 

становится

(Action<string>){x => {startNewWindow(x);}, 
      new object[] {srUrl} 

Теперь ссылка функция и правильная копия строки сохраняются для вызова функции, и это Безразлично» что исходный srUrl выходит за пределы области к моменту начала потока. Я не уверен, разрешена ли фабрика задач массиву аргументов. диспетчеры обычно имеют перегрузку для этого, поэтому, возможно, вы хотите, чтобы ваше окно позаботилось об этом.

Теперь вы делаете это несколько раз, поэтому вам может понадобиться обернуть аргументы каждый раз, когда они будут переданы.

+0

Спасибо за ответ. На самом деле я решил свою проблему, написав другое приложение, которое читает url из файла. Так что теперь я запускаю exes вместо новых окон. Иногда эти новые exes дают ошибки, но программное обеспечение продолжает работать :) Но ваш ответ действительно профессионален, мне это нравится. – MonsterMMORPG

+1

@MonsterMMORPG Этот ответ может звучать логично, но это неправильно. Закрытие будет фиксировать локальную переменную (которая называется свободной переменной). См. Также здесь: http://www.codethinked.com/c-closures-explained – ChrisWue

+0

Если это было верно, тогда ваш код сломался, даже показывая окно. После отображения окна srUrl не используется. – surfen

1

У меня была аналогичная проблема некоторое время назад.

Ошибка возникает из-за того, что ваше окно выходит из сферы действия, и сборщик мусора уничтожает его.

Использование ShowDialog() должно решить проблему. Обратите внимание, что это не будет блокировать другие потоки, потому что окно будет модальным только в вызывающем потоке.

private void NewWindowThread<T, P>(Func<P, T> constructor, P param) where T : Window 
{ 
    Thread thread = new Thread(() => 
    { 
     System.Windows.Threading.Dispatcher.Run(); 
     T w = constructor(param); 
     w.ShowDialog(); 
     w.Dispatcher.InvokeShutdown(); 
    }); 
    thread.SetApartmentState(ApartmentState.STA); 
    try 
    { 
     thread.Start(); 
    } 
    catch 
    { 
     // log&handle exceptions 
    } 
} 
+0

Если true ... вы можете сделать что-то похожее, установив событие в загруженном событии и ожидая этого события перед выходом из делегата. – Yaur

+0

Это имеет смысл, но не блокирует ли пользовательский интерфейс вновь созданного окна? – surfen

+0

благодарю вас за ответ. собираюсь попробовать сейчас. – MonsterMMORPG

2

Я боролся с этой проблемой с клиентом, и вот что я нашел.

Мы работаем над приложением WPF, которое выполняет много потоков и обработки рабочего стола. Это исключение неожиданно начало появляться, и я начал делать рытье. Я наконец-то нашел виновника после того, как примерно через час исследования:

 var worker = new BackgroundWorker(); 
     worker.DoWork += (o, ea) => Dispatcher.BeginInvoke(new Action(() => 
     { 
      //do some heavy processing here, plus UI work, then call another method. 

      //inside that other method, I found this: 
      var thread = new Thread(() => 
      { 
       //do some heavy processing. 
      }) { IsBackground = true }; 
      thread.Start(); 
     })); 

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

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