在一个非常简单的winform应用程序中死锁

时间:2013-01-08 08:25:53

标签: winforms multithreading

我创建了一个非常简单的winform应用程序,它上面有一个表单和一个按钮。其点击事件已连线,如下所示。如果单击该按钮,应用程序将按预期运行,即ExecTasks退出。如果用lock(this)替换lock语句,ExecTasks将不会退出,调试器会在Exec中的代码中显示sleep / wait / join中的线程。问为什么锁定对象的选择会改变这种行为 - 为什么表单实例不是一个有效的选择?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TestDeadlock
{
public partial class Form1 : Form
{
    private object _lock = new object();
    public Form1()
    {
        InitializeComponent();
    }

    private void Button1Click(object sender, EventArgs e)
    {
        Task.Factory.StartNew(ExecTasks);
    }

    private void ExecTasks()
    {
        lock (_lock) /* replace by lock(this) to see the blocked behavior */
        {
            var taskList = new List<Task>();
            for (var i = 0; i < 2; ++i)
            {
                taskList.Add(Task.Factory.StartNew(Exec));
            }
            Task.WaitAll(taskList.ToArray());
        }
    }

    private void Exec()
    {
        Invoke((Action)delegate{});
    }
}
}

1 个答案:

答案 0 :(得分:2)

我看到了这种阻止行为。当您调用Invoke方法时,它会调用Control.FindMarshalingControl方法,该方法实现如下:

private Control FindMarshalingControl()
{
    lock (this)
    {
        Control parentInternal = this;
        ....
    }
}

以下是类似问题的链接:

Control.BeginInvoke will also be blocked