2011-05-03 51 views
8

目前我與WinForms的工作(在C#),我要在後臺運行應用程序跨線程異常。爲此我使用異步。當我運行應用程序它顯示一個異常,如解決的WinForms

"Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on."

我該如何解決這個錯誤?

+0

的[與CrossThread幫助我嗎?]可能重複(http://stackoverflow.com/questions/337165/help-me-with-that-c​​rossthread)的[爲什麼我會得到這個 – jgauffin 2011-05-03 11:46:35

+0

可能重複錯誤:「跨線程操作無效:從比它創建的線程以外的線程訪問控制lbFolders」(http://stackoverflow.com/questions/244591/why-am-i-getting-this? -errorcross線程操作不化有效控制lbfolders) – 2011-05-03 13:11:03

回答

9

在作出方法調用的控制,如果主叫方是在不同的線程比對照創建的一個,您需要使用Control.Invoke調用。這裏是一個代碼示例:

// you can define a delegate with the signature you want 
public delegate void UpdateControlsDelegate(); 

public void SomeMethod() 
{ 
    //this method is executed by the background worker 
    InvokeUpdateControls(); 
} 

public void InvokeUpdateControls() 
{ 
    if (this.InvokeRequired) 
    { 
     this.Invoke(new UpdateControlsDelegate(UpdateControls)); 
    } 
    else 
    { 
     UpdateControls(); 
    } 
} 

private void UpdateControls() 
{ 
    // update your controls here 
} 

希望它有幫助。

+0

你好謝謝你給了性反應的我想要什麼ü提供代碼,其實我叫thred在button_click event..but它永諾去別的部分.. ..not進入到這個如果(this.InvokeRequired) { this.Invoke(新PerformSomeActionDelegate(MyAction)); } – Victor 2011-05-03 11:47:22

+0

@Victor:這意味着此時不需要Invoke。確保線程中執行的所有代碼執行「安全」(調用)調用來更新表單的控件。 – 2011-05-03 11:49:21

+0

我不能得到丹尼爾我可以在這裏發佈我的代碼.. – Victor 2011-05-03 12:01:24

3

大多數情況下,使用WinForms做這類事情的最好方法是使用BackgroundWorker,它可以在後臺線程上運行你的工作,但爲你提供一個很好的清理方法來向UI報告狀態。

在很多日常的.NET編程中,明確地創建線程或調用.Invoke表明您沒有充分利用框架的優勢(當然,有許多合法的原因可以做低級別也就是說,人們有時會意識到它們不太常見)。

+0

謝謝你給我的迴應,我正在使用這個(在上面給出的鏈接)我的應用程序中的後臺代碼。但這是顯示錯誤... – Victor 2011-05-03 11:39:34

+2

@Victor - 你必須使用.Invoke(請參閱其他人的例子),或使用BackgroundWorker.ReportProgress方法(以及它引發的ProgressChanged事件)來訪問表單。如果我使用的是BackgroundWorker,我總是會贊成ReportProgress通過直接Invoke調用。 – 2011-05-03 11:42:20

2

你需要的,如果調用需要你想更新控制檢查。事情是這樣的:

Action<Control, string> setterCallback = (toSet, text) => toSet.Text = text; 

void SetControlText(Control toSet, string text) { 
    if (this.InvokeRequired) { 
    this.Invoke(setterCallback, toSet, text); 
    } 
    else { 
    setterCallback(toSet, text); 
    } 
} 
1

,你可能會發現有用的模式是做在與GUI交互功能,頂部的檢查,看看您是否在正確的線程運行與否和具備的功能調用本身如果需要。就像這樣:

public delegate void InvocationDelegate(); 

    public void DoGuiStuff(){ 
     if (someControl.InvokeRequired){ 
     someControl.Invoke(InvocationDelegate(DoGuiStuff)); 
     return; 
     } 

     //GUI manipulation here 
    } 

使用這種模式 - 如果你是在方法被調用它不調用它本身正確的線程,但如果你是在不同的線程它會調用自身,然後返回(所以GUI操作邏輯只能以任何一種方式調用)。

0

從調用更新開始調用

// you can define a delegate with the signature you want 
public delegate void UpdateControlsDelegate(); 

public void SomeMethod() 
{ 
    //this method is executed by the background worker 
    InvokeUpdateControls(); 
} 

public void InvokeUpdateControls() 
{ 
    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(new UpdateControlsDelegate(UpdateControls)); 
    } 
    else 
    { 
     UpdateControls(); 
    } 
} 

private void UpdateControls() 
{ 
    // update your controls here 
} 
+0

嗨Pankaj allready我已經嘗試這段代碼,但invokerequired allways錯誤,當它是真的...我打電話invokerequired在我的按鈕單擊事件..... – Victor 2011-05-03 13:00:29

+0

替換此與您的buttonid並再次檢查。 – Pankaj 2011-05-03 13:07:50

+0

我寫了這樣的代碼private void btnsiteranks_Click_1(object sender,EventArgs e) {InvokeUpdateControls(); } 公共無效InvokeUpdateControls() { 如果(this.InvokeRequired) { this.BeginInvoke(新PerformSomeActionDelegate(Geturls)); } else { Geturls(); } } – Victor 2011-05-03 13:11:20

0

的用戶界面的變化可以用Control.Invoke()來完成的方法,該橫線程異常可以使用下面的代碼段來解決。

void UpdateWorker() 
{ 
    //Here ddUser is the user control 
    //Action to be performed should be called within { } as like below code 
    if (this.ddUser.InvokeRequired) 
     ddUser.Invoke(new MethodInvoker(() => { ddUser.Size = new Size(100, 100); })); 
} 
相關問題