2011-11-08 216 views
0

我在實現以下方面遇到了一些麻煩:C#事件冒泡

Form1有兩個按鈕「驗證」和「取消」,也有一個BackgroundWorker。 Class1有一個繁重的處理方法。

單擊「驗證」調用DoWork哪些繁重工作是Class1的一種方法。我設法在我的DoWork中「監聽」進度更改事件,這些事件源於Class1方法。

現在,我試圖取消點擊按鈕取消按鈕時沉重(在方法內)。

private void buttonCancelValidation_Click(object sender, EventArgs e) 
    { 
     backgroundWorker.CancelAsync(); 
    } 

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Class1 obj = new Class1(); 
     obj.ProgressChanged += (s, pe) => backgroundWorker.ReportProgress(pe.ProgressPercentage); 

     //---> Here a i'm trying to "tell" class1 that if the "Cancel" button was clicked then I want to abort ASAP the HeavyMethod operation. 

     obj.HeavyMethod(); 

     //followed by the cancel of BackgroundWorker DoWork 
     if (backgroundWorker.CancellationPending 
     { 
      e.Cancel = true; 
     } 
    } 

感謝您的幫助!

+0

有什麼問題,做到這一點? –

+0

@Charles如何從FORM1告訴另一個類對象的方法,取消被點擊。 – Libas

回答

0

你的HeavyMethod()代碼必須能夠訪問一些,比如說布爾變量,它應該表明它是否需要立即返回。您將多久檢查一次HeavyMethod()代碼中的變量值,將會改變用戶單擊「取消」按鈕和實際停止操作之間的延遲時間。

bool cancelValidationRequest = false; 
private void buttonCancelValidation_Click(object sender, EventArgs e) 
    { 
     cancelValidationRequest = true; // this will cause HeavyMethod return asap 
     backgroundWorker.CancelAsync(); // this makes requet to thread to stop, but it still in HeavyMethod... 
    } 

和內部HeavyMethod()

private void HeavyMethod() 
{ 

    //execute heavy code 
    if(cancelValidationRequest) return; 

    // continue execute heavy code 
    if(cancelValidationRequest) return; 

    ..... 
    .... 
} 

這樣的事情,只是給一個想法。

編輯

由於Wizetux指出的那樣,你必須注意的事實是bolean值(在這種特殊情況下)是由不同的線程操作。

希望這會有所幫助。

+0

正如他所說,您需要定期檢查終止請求:http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx –

+1

由於您將設置並從兩個不同的線程獲取bool的值,您將不得不擔心此任務的線程安全性,以免最終出現競爭狀態。我相信backgroundWorker對象在內部執行此操作。 – Wizetux

+0

@Tigran大聲笑,簡單... eheheh。 Obj在DoWork中瞬間完成,所以在ButttonCancelValidation中是未知的。可以在Class1中使cancelValidationRequest成爲一個靜態屬性嗎?做了一個快速測試,它是好的。 – Libas

2

不知道HeavyMethod是如何工作的,唯一的辦法就是讓線程等到HeavyMethod完成,或者提供一種方法來從obj類中插入HeavyMethod。

您可以讓Class1接受對backgroundWorker對象的引用,以便HeavyMethod可以檢查CancellationPending標誌的值並在該方法中中斷。如果您的HeavyMethod有一個循環或一組較小的任務,您可以在這些任務之間檢查該標誌以便儘早打破或返回該方法,這隻會起作用。

你可以像這樣

public class Class1 
{ 
    private BackgroundWorker _backgroundWorker = null; 
    public Class1(BackgroundWorkerThread worker) 
    { 
    _backgroundWorker = worker; 
    // rest of constructor 
    } 

    public void HeavyWorker() 
    { 
     // Heavy work 

     // Have we been cancelled. 
     if (_backgroundWorker != null && _backgroundWorker.CancellationPending) 
     { 
     // perform clean up and return 
     } 

     // Perform more heavy work. 
    } 
} 

private void backgroundWorker_DoWork(...) 
{ 
    Class1 obj = new Class1(backgroundWorker); 

    obj.HeavyMethod(); 
} 
+0

我只是在HeavyMethod中讀取一個文件,在一個循環中,所以我可以在該循環中中止它。 如果這是你的選擇,你會去你的第一個解決方案或第二個? 我想我在某個地方讀到BGW傳遞給另一個類對象不是個好主意。 – Libas

+0

我不記得任何關於將BGW傳遞給另一個類對象的問題,只要該對象僅在執行backgroundWorker期間發生。因爲一旦線程完成工作,應該處理對工作者的引用的對象。這個問題是當你開始引用陳舊的後臺工作者時。我只想把上面的檢查放在循環中,如果你取消了,不要忘記關閉文件。 – Wizetux

+0

我會盡力發現,以確保我不會搞亂概念。 因此,這是完美的,將使用此解決方案,已在另一個項目中使用過,但實際上我對這種方法有點不確定! 謝謝! – Libas