Parsley
Parsley

Reputation: 21

Threading issue in C# using BackgroundWorker

Can some kind soul please explain why the following psudocode would not work. The problem is that the lock can never be aquired on the backgroundWorker (Monitor.TryEnter(bw)) when called from a new thread. If I call it from the main UI thread it works fine.

Thanks P

public class MyClass 
{
    private BackgroundWorker bw;

    private void Button_Click(object sender, EventArgs e)
    {
        System.Threading.Thread t = 
            new System.Threading.Thread(new System.Threading.ThreadStart(DoStuff));
        t.IsBackground = true;
        t.Start();
    }

    private void DoStuff()
    {

        if (Monitor.TryEnter(bw))
        {
              WorkDetails wd = new WorkDetails('some stuff here');
              bw.RunWorkerAsync(wd);

              // etc... etc...
        }
    }
}

Upvotes: 2

Views: 659

Answers (2)

Ohad Schneider
Ohad Schneider

Reputation: 38162

I'm not sure you are using the background worker (BGW) as it was intended

The idea behind it, usually, is that you don't create threads yourself but rather specify to the BGW what you want to be done asynchronously. so your code should look like:

private BackgroundWorker bw = new BackgroundWorker ();
ctor 
{
    bw.DoWork += (sender, e) => DoStuff();
}

private void Button_Click(object sender, EventArgs e)
{
    bw.RunWorkerAsync();
}

For more information, see here

comments:

  1. As a rule of thumb, never lock on arbitrary objects (like you do on bw) but rather on objects whose sole purpose is locking. I recommend you read Jon Skeet's excellent multi threading guide
  2. You can add the BGW declaratively via the designer, saving yourself the instantiation and event hooking code

Upvotes: 1

Scott Langham
Scott Langham

Reputation: 60431

Are you missing a Monitor.Exit at the end of the if block. Without a Monitor.Exit, whichever thread first does a Monitor.TryEnter successfully will be the only thread that can enter again.

Upvotes: 1

Related Questions