2012-05-16 71 views
3

在保持一些代碼,我發現我們有一個後臺工作無限掛斷。工作人員需要訪問腳本文件。如果沒有定義腳本文件,則會編寫原始代碼以彈出文件對話框,以允許用戶選擇一個。它看起來是這樣的:文件對話框,從後臺工作

private void bgworker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ... snip ... 

    if (String.IsNullOrWhitespace(scriptFile)) 
    { 
     scriptFile = PromptForScript(); 
    } 

    ... snip ... 
} 

private string PrompForScript() 
{ 
    string script = ""; 
    OpenFileDialog openDialog = new OpenFileDialog(); 

    if (openDialog.ShowDialog() == DialogResult.OK) 
    { 
     script = openDialog.FileName; 
    } 

    return script; 
} 

我讀了一些關於MethodInvoker,但幾乎所有的調用方法需要您從控制調用它們。有問題的後臺工作人員是從單獨的課程運行的,該課程不延伸Control。我是否會使用bgworker爲此類調用該類的表單?或者是否有另一種中斷用戶輸入的線程?

+1

FWIW - 一個設計考慮是檢查該文件是否存在等(隨後提示用戶)運行後臺工作之前,假設線程首先被拉開序幕通過用戶交互。我通常更喜歡在UI(表單)調用的上下文中保持「表單類型」調用(如打開對話框),使業務邏輯(運行腳本)保持獨立。 –

+0

不是一個漂亮的解決方案,但是,我將調用回調到主UI線程,將文件名設置爲全局變量,然後從我的子類調用另一個檢索全局變量的方法。總之,1)要求後臺工作者; 2.)bgworker實例化子類的對象並調用啓動事件的類中的方法; 3.)主班正在收聽活動; 4.)在事件處理程序中,調用方法(包含InvokeRequired檢查); 5.)在GUI線程上從用戶獲取文件名; 6。)從子類中,調用另一個檢索文件名值的方法。 –

回答

3

不建議從後臺工作者DoWork事件處理程序調用UI。 BackgroundWorker是爲了在非UI線程上工作以保持UI響應。在使用RunWorerkAsync開始BackgroundWorker對象之前,您應該詢問任何文件信息。

+0

這通常是我所傾向的。我是一個非常小的程序員,在一個相當大的應用程序上工作,所以我有點猶豫是否會在結構上花費太多時間,但在運行線程之前進行檢查是有意義的。 – KChaloux

-2

那麼,Form類有一個Invoke方法,所以傳遞表單實例到後臺工作類應該工作。

+0

正如問題中所提到的,在這種情況下,沒有可從其調用調用方法的窗體類。 – KChaloux

+0

表單可以傳遞給該類。 OP剛纔說班級不是控制人員,並問他是否可以使用該表格。簡短的答案是'是'。 – zmbq

+0

調用調用將阻止後臺工作線程等待UI線程完成操作;如果UI線程以任何方式等待BackgroundWorker(如進度或完成),那麼您會遇到死鎖。不建議。 –

1

你想要做的是捕獲UI線程上SynchronizationContext並傳遞到一起的後臺工作。 BackgroundWorker可以在上下文中調用Send()(同步,如Invoke)和Post()(異步,如BeginInvoke),以調用回正確的UI線程。也就是說,在這種情況下可能不需要BackgroundWorker-普通的線程池線程可以做得很好。

這(略有修改)的代碼塊http://msmvps.com/blogs/manoj/archive/2005/11/03/74120.aspx應該給你的總體思路:

private void button1_Click(object sender, EventArgs e) 
{ 
    // Here we are on the UI thread, so SynchronizationContext.Current 
    // is going to be a WindowsFormsSynchronizationContext that Invokes properly 
    ctx = SynchronizationContext.Current; 
    ThreadPool.QueueUserWorkItem(
     // This delegate is going to be invoked on a background thread 
     s => { 
      // This uses the context captured above to invoke 
      // back to the UI without the "messy" referencing 
      // of a particular form 
      ctx.Send(s2 => 
      { 
       // Interact with your UI here- you are on the UI thread 
      },null); 
     } 
    ); 
} 
0

如果某種形式的使用BGworker在另一個類中揭開序幕長期運行的過程中,爲什麼不表單(或演示者,取決於UI架構)處理錯誤狀態的處理?

也許,只是傳回一些狀態result(或扔,你可以在UI處理非常有針對性的,具體的除外)?

離開背景工人,以確定是否有錯誤,但留下移交的誤差(特別是示出了消息框的UI部分)到上層。

很抱歉,這並沒有更具體的代碼,但它可以去取決於你的系統是如何架構有很多不同的方式。