簡體   English   中英

如何將我的代碼適合后台工作人員?

[英]How can I fit my code into a Background Worker?

我建立了一個執行以下操作的表單:

  1. 抓取目錄中的所有文件路徑(文件采用指定的命名約定)
  2. 使用分隔符解析文件路徑
  3. 輸出具有指定格式的文本文件。

問題在於某些目錄是數百個演出,它們凍結了表單用戶界面,直到完成該過程為止。 我已經閱讀了一些有關背景工作者的文章,據我所知,代碼中數據密集型部分位於DoWork方法下。 但是,當我嘗試將代碼實現到DoWork方法中時,遇到了“跨線程操作無效:”錯誤。 我查找了該錯誤,但是我根本不了解如何在不重新設計程序整個結構的情況下解決該錯誤。

我的代碼很長,但是我可以根據需要提供。

最好的方法是重新編寫代碼,使其不使用UI組件。

完成后,您可以使用ReportProgress / ProgressChanged和RunWorkerCompleted刷新UI。

如果您仍然想使用UI組件,則可以嘗試Invoke:

this.Invoke(new Action(() => 
    {
        //code that uses UI for instance :
        //this.TextBox1.Text = "test"
    });

造成這種情況的最可能原因是您正在從后台工作人員訪問控件所擁有的值。 除非一個調用返回到GUI線程,否則就無法從這些對象進行寫入讀取 長話短說,當我嘗試從我的工作線程中讀取文本框的值時遇到了同樣的問題,盡管它是讀取的,但失敗了。

我建議您從后台工作進程中刪除所有數據訪問/更新,以解決此問題。

這是我寫的有關后台工作者的文章

C#WPF:Linq在BackgroundWorker DoWork事件中失敗

C#WPF:線程,控件更新,狀態欄和取消操作示例全部合而為一

當您嘗試從BackGroundWorker寫入窗體上的控件時發生錯誤。 編寫控件時,您需要添加InVoke。 請參閱以下網頁: https : //msdn.microsoft.com/zh-cn/library/ms171728%28v=vs.85%29.aspx? f = 255 & MSPPError =-2147217396

您的代碼從線程創建對象之外的線程訪問GUI控件的屬性。 WindowsForms / WPF在內部進行檢查,查看您是否正在從另一個線程訪問控件的屬性並引發異常。

我建議您使用MVVM模式。 另外,BackgroundWorker現在被認為已過時,您應該將Tasks與async / await關鍵字一起使用。 這是我在WPF應用程序中的處理方式:

public class ViewModel : INotifyPropertyChanged
{
    ...

    public string PathInfo { ... } // raises INotifyPropertyChanged.PropertyChanged event from the setter
    public RelayCommand ProcessPathsCommand { get; set; }

    public ViewModel()
    {
        ProcessPathsCommand = new RelayCommand(ProcessPaths);
    }

    public async void ProcessPaths()
    {
        // disable the command, which will lead to disabling a button bound to the command
        ProcessPathsCommand.IsEnabled = false;

        try
        {
            // run processing on another thread
            await Task.Run(() =>
            {
                // emulate hard-work
                Thread.Sleep(5000);
                // update the property on the view model, which will lead to updating a textblock bound to this property                
                // in WPF you can update the bound property right from another thread and WPF will automatically dispatch PropertyChanged event to the main UI thread. In WinForms this would lead to an exception.
                PathInfo = "Here are the results: bla bla bla";
            });
            // In WinForms you would need to update the bound property here:
            // Thanks to Tasks and await this line of code will be executed only after the task is finished
            // PathInfo = resultFromTaskThread;
        }
        finally
        {
            ProcessPathsCommand.IsEnabled = true;
        }
    }

我們中的許多人都記得在WindowsForms中,我們必須使用Control.Invoke()從另一個線程更新GUI控件(即使不需要,我們中的許多人仍然在WPF中使用Dispatcher.Invoke)。 有了WPF,Microsoft終於使我們更容易了! WPF自動將PropertyChanged事件調度到主GUI線程,因此我們可以簡單地從另一個線程更新視圖模型上的屬性(綁定到UI上的某些控件),屬性設置器將引發PropertyChanged事件,WPF將自動將此事件調度到UI線程!
您還可以在這里閱讀有關此內容:
MVVM應用程序中的多線程和分派

如果您需要更多詳細信息,請隨時告訴我。

如果TB_path或TB_TrackingNum是UI元素(我懷疑是),那么您正在嘗試訪問UI。

如果僅將UI元素綁定到公共屬性,則可以從BackgroundWorker訪問公共屬性。

暫無
暫無

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

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