簡體   English   中英

具有ProgressBar的BackgroundWorker-跨線程操作無效

[英]BackgroundWorker with ProgressBar - Cross-thread operation not valid

我的表格申請中有服務電話。 單擊我的按鈕后,我將調用我的服務方法。 這是我的代碼塊:

void listBox_SelectedValueChanged(object sender, EventArgs e)
    {
        if (listBox.SelectedItem.Equals("Demo"))
        {
            progressBar1.Visible = true;
            backgroundWorker1.RunWorkerAsync();
        }
    }

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {   
        ObservableCollection<FilterInfo> filterInfos = new ObservableCollection<FilterInfo>();
        FilterInfo myFilterObj = new FilterInfo("SUPERVISOR", userName);
        filterInfos.Add(myFilterObj);
        ObservableCollection<DEMOBec> demos = demoSvc.GetDemoByFilter(filterInfos, false);
        dt = new Converter<DEMOBec>().ConvertDataTable(demos.ToList());
    }

在調用該服務之前,我使ProgressBar(樣式=選取框)可見。 但是由於跨線程問題,我無法使其在完整的方法中不可見。

當我嘗試在BGWorker的Completed事件中的UI線程中執行某些操作時,

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        progressBar1.Visible = false;
    }

我有一個例外:

跨線程操作無效:控件“ Form1”從創建該線程的線程之外的線程訪問。

我該如何解決這個問題?

您需要使用Invoke()方法

    private delegate void ToDoDelegate();
    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Invoke(new ToDoDelegate(() => progressBar1.Visible = false));
    }

Invoke()的詳細信息http://msdn.microsoft.com/de-de/library/System.Windows.Forms.Control.Invoke(v=vs.110).aspx

這是我一直喜歡使用的小段代碼,我不記得很久以前將其放在Dropbox中的位置。

public static class ControlExtensions
{
    public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                               Func<TControl, TResult> func)
      where TControl : Control
    {
        return control.InvokeRequired
                ? (TResult)control.Invoke(func, control)
                : func(control);
    }

    public static void InvokeEx<TControl>(this TControl control,
                                          Action<TControl> func)
      where TControl : Control
    {
        control.InvokeEx(c => { func(c); return c; });
    }

    public static void InvokeEx<TControl>(this TControl control, Action action)
      where TControl : Control
    {
        control.InvokeEx(c => action());
    }

}

用法

this.InvokeEx( x => Progressbar1.Visible = false); //Note 'x' could be any variable

這樣,您不必每次都鍵入所有內容,並且使用非常簡單。 只需將此權利添加到表單類的末尾(在最后一個括號關閉之后)。 您可以使用它來安全地執行任何跨線程操作。

修改UI線程上ProgressBar的可見性。

Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)
                    delegate()
                    {
                        progressBar1.Visible = false;
                    });

我認為在RunWorkerCompleted事件中不會引發異常(如評論中所述)。 我的建議是,您嘗試在DoWork事件中訪問UI cmponent的行會觸發它。

嘗試將DoWork事件中所需的數據放入DoWorkEventArgs e 這樣的討論在SO上提供了大量示例。

工作完成后,也可以使用事件args向“主UI線程”提供已修改/新的數據,如下所示:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
    // do some work
    e.Result = ... ; // modified/new data
}

並以以下方式檢索它:

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    var newData = (CastToWhatever) e.Result;
}

希望對您有幫助=)

編輯

您在backgroundWorker1_RunWorkerCompleted()代碼絕對不是異常的來源。 它構建了一個簡單的示例來說明我的觀點:

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync(textBox1.Text);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    var num = Int32.Parse(e.Argument.ToString()) + 1;
    backgroundWorker1.ReportProgress(num);
    e.Result = num;
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = (int)e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    textBox1.Text = e.Result.ToString();
}

它能做什么? 在WinForm上,有一個帶有數字的TextBox ,一個ProgressBar和一個用於啟動BackGroundWorkerButton

worker從TextBox (UI線程)獲取該數字, DoWork將其增加1並將其保存為result (新線程) 另外,它將增加的數字報告給ProgressBar (跨線程)

最后, RunWorkerCompleted讀取結果並將新值存儲在TextBox (UI線程)中

因此,請重新檢查您的代碼;-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM