要存取 Windows Forms Controls 就必須考慮 Thread-Safe的問題 (參閱: 這裡)。如果 InvokeRequired 是 True,就必須使用 Invoke method 來保證 Thread-Safe。
然而,要使用 Invoke method,必須確定到這個 Form 或是 Control 已經擁有 '視窗控制代碼' (window handle)。
在下列的情況下,Handle 才會存在:
若要使用InvokeRequired 判斷 cross-thread,必須排除 handle 不存在所造成的影響。
比較好的做法是: 使用 InvokeRequired 之前,先判斷 IsHandleCreated 為True。
[例如]:
private delegate void SetTextDelegate(string text, Color color, Font font);
private void SetText(string text, Color color, Font font)
{
if (IsHandleCreated)
{
// 已經排除沒有 handle 的情況
// 所以可用InvokeRequired 判斷是否為 cross-thread
if (InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
Invoke(d, new object[] { text, color, font });
}
else // use the RichTextBox control directly
{
txtLogging.AppendText(text);
txtLogging.SelectionColor = color;
txtLogging.SelectionFont = font;
}
}
}
相關連結:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
然而,要使用 Invoke method,必須確定到這個 Form 或是 Control 已經擁有 '視窗控制代碼' (window handle)。
在下列的情況下,Handle 才會存在:
- Form/Control 已經實體化( instantiated )且初始化 (initialized, first shown)
- Form 還沒被 closed (i.e., handle 還沒被 disposed)
- 相同 thread (表示不需要 Invoke)
- Form/Control 沒有 handle (沒有 handle 就不可能 Invoke)
若要使用InvokeRequired 判斷 cross-thread,必須排除 handle 不存在所造成的影響。
比較好的做法是: 使用 InvokeRequired 之前,先判斷 IsHandleCreated 為True。
[例如]:
private delegate void SetTextDelegate(string text, Color color, Font font);
private void SetText(string text, Color color, Font font)
{
if (IsHandleCreated)
{
// 已經排除沒有 handle 的情況
// 所以可用InvokeRequired 判斷是否為 cross-thread
if (InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
Invoke(d, new object[] { text, color, font });
}
else // use the RichTextBox control directly
{
txtLogging.AppendText(text);
txtLogging.SelectionColor = color;
txtLogging.SelectionFont = font;
}
}
}
相關連結:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
沒有留言:
張貼留言