1

単一のフォームと単一のボタンを持つ非常に単純な winform アプリを作成しました。そのクリックイベントは、以下に示すように接続されています。ボタンをクリックすると、アプリは期待どおりに動作します。つまり、ExecTasks は終了します。lock ステートメントを lock(this) に置き換えると、ExecTasks は終了せず、デバッガーは Exec のコードでスリープ/待機/結合のスレッドを表示します。ロックオブジェクトを選択するとこの動作が変わるのはなぜですか?フォームインスタンスが有効な選択ではないのはなぜですか?

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{});
    }
}
}
4

1 に答える 1

2

このブロッキング動作が見られます。Invoke メソッドを呼び出すと、次のように実装されている Control.FindMarshalingControl メソッドが呼び出されます。

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

同様の問題に関するリンクは次のとおりです。

Control.BeginInvoke もブロックされます

于 2013-01-08T08:38:54.020 に答える