Attempted to read or write protected memory. This is often an indication that other memory is corrupt
Asked Answered
S

3

8

I really do not understand how is this error happening at this code. Please check the code yourself

    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);
}

Now this code is where the error happening. I will also attach screenshot

        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
        {

        }
    }

This error causes whole software throw error and stop working even though i am calling them in new thread :(

This line throwing error System.Windows.Threading.Dispatcher.Run();

Please check also screenshot

enter image description here

C# 4.0 WPF

Sericin answered 2/4, 2012 at 19:36 Comment(3)
You're actually using two threads, the one in the Task and then the Thread, better to just place the code you want to run as startup code in the Thread.Sardou
@Sardou I also tried that still application crashing. And this is happening after a while not instantly. It runs like 30 minutes then crash. The crashing time changes.Mathewmathews
No, they say your memory is broken. It must be so! (btw that is the dumbest error message I have encountered after 'unspecified error').Supercilious
H
1

You are using a lambda as a thread function. This lambda is called on a new thread. At the moment the thread is actually created, it will look for the argument you supply, which is a local variable srUrl, but by the time this happens your function (dispatcherTimer_Tick) has already exited, so srUrl will be in a part of the stack that is no longer properly defined (hence the access violation). The easy fix is to define a variable in the class and stuff the srLoc there quickly. A more proper solution is to actually pass the srLoc as argument:

() =>
{
    startNewWindow(srUrl);
}

becomes

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

Now the function reference and a proper copy of the string are saved for the function call, and it doesn't matter that the original srUrl is out of scope by the time the thread kicks in. I'm not sure whether the task factory allows the argument array to be passed. dispatchers normally have an overload for this, so maybe you want to let your window take care of this.

Now you actually do this a few times, so you may need to wrap the arguments each time they are passed.

Huoh answered 3/4, 2012 at 8:7 Comment(4)
Thanks for answer. Actually i solved my problem via writing another application which reads the url from file. So i am starting exes now instead of new windows. Some times these new exes giving errors but software continue running :) But your answer is really professional i like it.Mathewmathews
@MonsterMMORPG This answer might sound logical but it is wrong. The closure will capture the local variable (which is called a free variable). See also here: codethinked.com/c-closures-explainedBrittle
If this was true then your code would break before even showing the window. After showing the window the srUrl is not being used.Rasia
@ChrisWue: thanks for the link. I use this when redirecting a call from another thread to the UI thread (with Dispatcher.BeginInvoke). If the closure would work, the wrapping would not be required, but if I don't, I get exactly the memory access violation mentioned here. So maybe the variable is supposed to be captured, but it isn't.Huoh
S
2

I have been battling this issue with a customer and here is what I found.

We are working on a WPF application that does a lot of threading and background worker processing. This exception suddenly started cropping up and I started doing some digging. I finally found the culprit after about an hour of investigating:

        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();
        }));

What appears to have been happening is that the background worker is finishing its work and returning from its execution. However, the thread that is created inside that background worker isn't done processing and returns only to find that the thread it was created on has already gone out of scope, thus resulting in the AccessViolationException.

In order to debug this, I would suggest paying close attention to where the exception happens and closely examining your call stack, which may or may not have been destroyed or lost depending upon whether or not you are inside a thread when the exception gets thrown.

Sidneysidoma answered 8/8, 2013 at 17:22 Comment(0)
R
1

I had similar problem some time ago.

The error occurs because your window goes out of scope and Garbage Collector destroys it.

Using ShowDialog() should solve the issue. Note that doing this won't block other threads because the window will be modal in the calling thread only.

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
    }
}
Rasia answered 2/4, 2012 at 19:51 Comment(2)
If true... you could do something simmilar by setting an event in the loaded event and waiting on that event before exiting the delegate.Tomasatomasina
This makes sense but wouldn't it block the UI of the newly created window?Rasia
H
1

You are using a lambda as a thread function. This lambda is called on a new thread. At the moment the thread is actually created, it will look for the argument you supply, which is a local variable srUrl, but by the time this happens your function (dispatcherTimer_Tick) has already exited, so srUrl will be in a part of the stack that is no longer properly defined (hence the access violation). The easy fix is to define a variable in the class and stuff the srLoc there quickly. A more proper solution is to actually pass the srLoc as argument:

() =>
{
    startNewWindow(srUrl);
}

becomes

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

Now the function reference and a proper copy of the string are saved for the function call, and it doesn't matter that the original srUrl is out of scope by the time the thread kicks in. I'm not sure whether the task factory allows the argument array to be passed. dispatchers normally have an overload for this, so maybe you want to let your window take care of this.

Now you actually do this a few times, so you may need to wrap the arguments each time they are passed.

Huoh answered 3/4, 2012 at 8:7 Comment(4)
Thanks for answer. Actually i solved my problem via writing another application which reads the url from file. So i am starting exes now instead of new windows. Some times these new exes giving errors but software continue running :) But your answer is really professional i like it.Mathewmathews
@MonsterMMORPG This answer might sound logical but it is wrong. The closure will capture the local variable (which is called a free variable). See also here: codethinked.com/c-closures-explainedBrittle
If this was true then your code would break before even showing the window. After showing the window the srUrl is not being used.Rasia
@ChrisWue: thanks for the link. I use this when redirecting a call from another thread to the UI thread (with Dispatcher.BeginInvoke). If the closure would work, the wrapping would not be required, but if I don't, I get exactly the memory access violation mentioned here. So maybe the variable is supposed to be captured, but it isn't.Huoh

© 2022 - 2024 — McMap. All rights reserved.