Reputation: 103
I have a problem with understanding multithreading. I will try to explain and hope you will understand what I mean.
I have a class form1
(inherited from Form
). This form can be opened several times. When one is opened, a worker thread will start with a global synchronized object which I pass on creating the form.
So every form has the same object to synchronize. This is necessary, because there is a another class which does some work (only one object can be alive). It is not allowed to do this work at the same time.
My problem is the following:
How can I synchronize all threads with the second work class without blocking all threads?
// from this form can be exist several objects
public partial class form1 : Form
{
...
private Object synchronizedObject;
public void SetSynchronizedObject(Object o)
{
synchronizedObject = o;
}
// executed threaded
public void DoWork()
{
while (bDoWork)
{
try
{
bool bLock = Monitor.TryEnter(synchronizedObject);
if (!bLock)
{
if (bDoWork)
{
this.BeginInvoke((MethodInvoker)delegate()
{
if (panel1 != null)
panel1.Visible = true;
});
}
Monitor.Enter(synchronizedObject);
if (bDoWork)
{
this.BeginInvoke((MethodInvoker)delegate()
{
if (panel1 != null)
panel1.Visible = false;
});
}
}
i++;
if (bDoWork)
{
this.BeginInvoke((MethodInvoker)delegate()
{
if (textBox != null)
textBox.Text = i.ToString();
});
}
}
finally
{
Monitor.Exit(synchronizedObject);
}
Thread.Sleep(1);
}
}
Then there is form2
. When form2
does its work, all threads should be blocked. The problem with my code is that form1
is blocking.
Upvotes: 0
Views: 83
Reputation: 4744
You want to synchronize your threads by using a shared synchronizedObject
. That's a good idea, but are you really sure synchronizedObject
is indeed shared between all the instances? There is a very simple way to really ensure this, without having to use a (potentially buggy) SetSynchronizedObject
method.
private static readonly Object synchronizedObject = new object();
Now you are sure synchronizedObject
is shared between all the instances.
I'm not sure this is the faulty part in your implementation (it depends how you were calling SetSynchronizedObject
), but it's very easy to ensure there is no potential bug there.
Upvotes: 0
Reputation: 5357
The problem you're trying to solve can be nicely approached with a "worker". Create a ConcurrentQueue<T>
, add "work" there. Start a worker thread (once)
ConcurrentQueue<T> _q;
void Worker()
{
while (true)
{
T element = _q.Dequeue();
if (element == null)
break;
// do work with element here
// obviously, it will happen one at a time
}
}
the code in example assumes you don't need the result
A better approach would be using "Limited concurrency SynchronizationContext", in which case you may use await/async.
Upvotes: 1