Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена
Я действительно не понимаю, как эта ошибка происходит в этом коде. Пожалуйста, проверьте код
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
{
}
}
эта ошибка вызывает ошибку всего программного обеспечения и перестает работать, даже если я вызываю их в новом потоке : (
эта строка бросает ошибку
3 ответов
вы используете лямбда в качестве функции потока. Эта лямбда вызывается в новом потоке. В момент поток создается, он будет искать аргументов, которая является локальной переменной srUrl, но когда это происходит, ваша функция (dispatcherTimer_Tick) уже завершился, поэтому srUrl будет в составе стека, что не правильно определены (отсюда нарушение прав доступа). Простое исправление-определить переменную в классе и быстро заполнить srLoc. Более правильное решение-фактически передать srLoc в качестве аргумента:
() =>
{
startNewWindow(srUrl);
}
становится
(Action<string>){x => {startNewWindow(x);},
new object[] {srUrl}
теперь ссылка на функцию и правильная копия строки сохраняются для вызова функции, и не имеет значения, что исходный srUrl выходит из области к моменту запуска потока. Я не уверен, что фабрика задач позволяет передавать массив аргументов. диспетчеры обычно имеют перегрузку для этого, поэтому, возможно, вы хотите, чтобы ваше окно позаботилось этот.
теперь вы действительно делаете это несколько раз, поэтому вам может потребоваться обернуть аргументы каждый раз, когда они передаются.
Я боролся с этой проблемой с клиентом, и вот что я нашел.
мы работаем над приложением 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.
чтобы отладить это, я бы предложил обратить пристальное внимание на то, где происходит исключение, и внимательно изучить ваш стек вызовов, который может быть или не быть уничтожен или потерян в зависимости от того, находитесь ли вы внутри потока, когда исключение получает бросили.
у меня была аналогичная проблема некоторое время назад.
ошибка возникает из-за того, что ваше окно выходит за рамки и сборщик мусора уничтожает его.
используя 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
}
}