c#锁定一个类但不是自己

时间:2015-06-27 20:52:16

标签: c# multithreading

我在理解多线程方面遇到了问题。我会尝试解释并希望你能理解我的意思。

我有一个班级form1(继承自Form)。这个表格可以打开几次。当打开一个工作线程时,工作线程将以全局同步对象开始,我传递该对象创建表单。

因此每个表单都有相同的对象进行同步。这是必要的,因为还有另一个类可以完成一些工作(只有一个对象可以存活)。不允许同时完成这项工作。

我的问题如下:

如何在不阻塞所有线程的情况下将所有线程与第二个工作类同步?

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

然后有form2。当form2完成其工作时,应阻止所有线程。我的代码存在的问题是form1正在阻止。

2 个答案:

答案 0 :(得分:1)

您尝试解决的问题可以通过“工作人员”很好地解决。创建一个ConcurrentQueue<T>,在那里添加“工作”。启动工作线程(一次)

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

示例中的代码假定您不需要结果

更好的方法是使用“Limited concurrency SynchronizationContext”,在这种情况下,您可以使用await / async。

答案 1 :(得分:0)

您希望使用共享的synchronizedObject来同步您的主题。这是一个好主意,但你真的确定synchronizedObject确实在所有实例之间共享吗?有一种非常简单的方法可以真正确保这一点,而无需使用(潜在的错误)SetSynchronizedObject方法。

    private static readonly Object synchronizedObject = new object();

现在您确保 synchronizedObject在所有实例之间共享。

我不确定这是你实施中的错误部分(这取决于你如何调用SetSynchronizedObject),但很容易确保那里没有潜在的错误。< / p>