一般的なハンドラーメソッドで処理されるイベントをスローするワーカースレッドを取得しました。実際には、イベントをスローするワーカースレッドを含むオブジェクトを作成したスレッドによってハンドラーメソッドが実行されるようにしたいと思います。
私は次のコードを試しました:
public partial class Form1 : Form
{
public event EventHandler Tested;
public Form1()
{
InitializeComponent();
Tested += new EventHandler(Form1_Tested);
}
private void Form1_Tested(object sender, EventArgs e)
{
Text = "Test";
}
private void Form1_Shown(object sender, EventArgs e)
{
#region Test 1
// Works normal in GUI-Thread directly
Form1_Tested(this, EventArgs.Empty);
#endregion
#region Test 2
// Works in worker thread and throws GUI exception
// because of foreign thread access
new Thread(new ThreadStart(delegate()
{
OnTested(EventArgs.Empty);
})).Start();
#endregion
#region Test 3
// Works in worker thread and returns to GUI-Thread
// to throw the event, so no need in eventhandler
// to use Control.Invoke();
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);
new Thread(new ThreadStart(delegate()
{
asyncOp.Post(new SendOrPostCallback(delegate(object obj)
{
OnTested(EventArgs.Empty);
}), null);
})).Start();
#endregion
}
protected virtual void OnTested(EventArgs e)
{
EventHandler tmpHandler = Tested;
if (tmpHandler != null)
tmpHandler(this, e);
}
}
使用しているスレッドをクローザーで見てみました
Thread.CurrentThread.ManagedThreadId;
ワーカースレッドを開始する前は、メインスレッドのIDは「1」です。UIスレッド内で、イベントを発生させる直前のスレッドID(ワーカースレッドの)は「4」です。ここで、ハンドラーメソッドのスレッドIDを詳しく見てみると、スレッドIDは「10」のようなものですが、代わりにIDが「1」であると予想していました。私はそれについて非常に混乱しています。
一般的に:私のスニペットはそれを行う正しい方法ですか、それともこれを行うためのベストプラクティス(または実際の例)は何ですか?
実際にワーカースレッドでInvokeを使用することは避けたかったのです。
よろしく、トーマス