Blog นี้จริงๆ แล้วเป็นการนำ Blog ที่เขียนค้างตอนปี 2014 (ช่วงที่อยู่กับ Project ที่ได้ แต่บ่น 555) มาเขียนต่อให้จบครับ แม้ว่าตอนนี้แนวทางการพัฒนาระบบเป็นแนว Web Application แล้ว แต่ยังมีงานบางส่วนที่ยังเป็น Desktop Application ครับ

ปัญหา
- เวลาจัดการงานด้าน UI มักจะเจอปัญหาที่เจอประจำเลย InvalidOperationException
Cross-thread operation not valid. Control accessed from a thread other than the thread it was created on.
- สาเหตุ เกิดจากตัว Control ของ WinForms ไม่เป็น Thread-Safe ครับ
- ทางแก้ไข มี 2 แบบครับ
- BackgroundWorker: ให้ Main Thread แอบสั่งทำงานแบบ Asynchronous ผ่าน Method dowork
- Invoke method: delegated จาก Main Thread ให้มาทำส่วนที่ต้องการแทนครับ
- คราวนี้ เราจะมา Focus เฉพาะในส่วนของ Invoke method
Invoke method
- การใช้งานง่ายมาครับ มี Pattern ดังนี้ครับ
if (<<CONTROL>>.InvokeRequired)
{
<<CONTROL>>.Invoke(new Action(() =>
{
<<YOUR LOGIC>>
}));
}
else
{
<<YOUR LOGIC>>
}- ตัวอย่าง
if (cboPortfolio.InvokeRequired)
{
cboPortfolio.Invoke(new Action(() =>
{
cboPortfolio._lookUpEdit.EditValue = o;
}));
}
else
{
cboPortfolio._lookUpEdit.EditValue = o;
}- ปัญหาที่พบ Code ในเคสที่ต้อง delegated จาก Method InvokeRequired() มันเหมือนกันเลยครับ !!!!
- จะว่าไปมันก็ขัดกับหลัก DRY (don’t repeat yourself) ครับ
- แนวทางแก้ไข - ทำ Extensions Method ของ Control ขึ้นมาสิ เพื่อให้ Dev ไม่ต้อง Copy Code ซ้ำๆ ดังนี้
public static class ControlExtensions
{
public static void InvokeIfRequired(this ISynchronizeInvoke obj
, MethodInvoker action)
{
if (obj.InvokeRequired)
{
var args = new object[0];
obj.Invoke(action, args);
}
else
{
action();
}
}
}Reference
- Control.InvokeRequired Property (System.Windows.Forms) | Microsoft Docs
- How to make thread-safe calls to controls - Windows Forms .NET | Microsoft Docs
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.



