0

I lock on a global object in order to synchronise communication to an external device from various threads, which is working fine.

I want to user a slider control to set values which I then send to my external device, so I'm using its Scroll event to listen for changes before sending them off to the device.

The problem is, I need to lock on the global object before communicating with the device, as follows:

private void slider_Scroll(object sender, EventArgs e)
{
    lock(lockObject)
    {
        //send slider values to external device
    }
}

The above always hangs indefinitely on attempting to gain the lock. The rest of my code has been working fine, so I don't think I have a genuine race condition - I'm assuming this is happening because it's running on the UI thread and that it's a Bad Idea to block on the UI thread? I could be wrong.

However, if this is the case, I'm guessing I need to wrap the above code in a method and somehow invoke it on the 'main' thread from the UI thread?

How can I achieve this?

digital_fate
  • 567
  • 1
  • 5
  • 15

1 Answers1

1

Definitely never a good idea to use lock from the main UI thread. Add a BackgroundWorker() control to the form and pass the slider value into the RunWorkerAsync() method. You can retrieve the value in the DoWork() handler via e.Argument, and safely use lock from there.

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Many thanks for your answer. I imagine this will probably work. Is there a lot of overhead in spinning off a BackgroundWorker each time the slider is moved? Would it be possible to use a delegate instead? – digital_fate Oct 30 '13 at 15:33
  • The BackgroundWorker() will throw an exception if you try to run it again while it is already running. You can check its IsBusy() property to decide whether to run it or not. Whatever the method, it might make more sense to wait until the control stops changing and only send the last value. What control exactly are you using?..."slider" could be several different ones. – Idle_Mind Oct 30 '13 at 15:43
  • Just a Windows Form 'slider'. It's straightforward to just send the last value, thanks. In order to read values from my external device, I imagine I'll have to return the value to the UI element via the BackgroundWorker's RunWorkerCompleted event? – digital_fate Oct 30 '13 at 16:09
  • Yes...if you set WorkerReportsProgress() to True, then you can alternatively use ReportProgress() and the ProgressChanged() event. – Idle_Mind Oct 30 '13 at 16:11