为什么我在backgroundworker progresschanged事件中更新标签时遇到跨线程异常?

时间:2016-03-24 17:10:20

标签: c# .net winforms

我有一个背景工作者,我在里面开始一个新的背景工作者

DirectoryInfo MySubDirectory;
List<FileInfo> l;
object[] CurrentStatus;

private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int countmore = 0;
    try
    {
        DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
        for (int i = 0; i < MySubDirectories.GetLength(0); i++)
        {
            MySubDirectory = MySubDirectories[i];

            l = new List<FileInfo>();
            if (_FileCountingWorker.IsBusy == false)
                _FileCountingWorker.RunWorkerAsync();

            CurrentStatus = new object[6];
            int totalFiles = l.Count;
            CurrentStatus[3] = i.ToString();
            countmore += totalFiles;
            CurrentStatus[4] = countmore;
            _FileProcessingWorker.ReportProgress(0, CurrentStatus);

            string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;

            foreach (FileInfo MyFile in l)
            {
                CurrentStatus = new object[6];
                if (_FileProcessingWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                 }

                 if (MyFile.Extension.ToLower() == ".cs" || MyFile.Extension.ToLower() == ".vb")
                 {
                     string CurrentFile = "Current File: " + MyFile.Name;
                     string CurrentFileWithPath = MyFile.FullName;

                     CurrentStatus[0] = CurrentDirectory;
                     CurrentStatus[1] = CurrentFile;
                     _FileProcessingWorker.ReportProgress(0, CurrentStatus);

                     List<string> Result = SearchInFile(CurrentFileWithPath, "if");

                     if (Result != null && Result.Count > 0)
                     {
                         CurrentStatus[2] = Result;
                         _FileProcessingWorker.ReportProgress(0, CurrentStatus);
                      }
                  }
              }
          }
      }
      catch (Exception err)
      {
          return;
      }
  }

我正在检查其他后台工作人员是否忙碌如果没有启动它

if (_FileCountingWorker.IsBusy == false)
    _FileCountingWorker.RunWorkerAsync();

在新的backgroundworker dowork活动中

private void _FileCountingWorker_DoWork(object sender, DoWorkEventArgs e)
{
    CountFiles(MySubDirectory, l);
}

在CountFiles中

int countingFiles = 0;
private void CountFiles(DirectoryInfo di, List<FileInfo> l)
{
    try
    {
        l.AddRange(di.EnumerateFiles());
    }
    catch
    {
        string fff = "";
    }

    try
    {
        if (di.FullName != BasePath)
        {
            IEnumerable<DirectoryInfo> subDirs = di.EnumerateDirectories();
            if (subDirs.Count() > 0)
            {
                foreach (DirectoryInfo dir in subDirs)
                {
                    CountFiles(dir, l);
                    countingFiles += 1;
                    if (countingFiles == 8382)
                    {
                        string hhhhh = "";
                    }
                    CurrentStatus[5] = countingFiles;
                    _FileCountingWorker.ReportProgress(0,CurrentStatus);
                }
            }
        }
    }
    catch 
    {
        string yyy = "";
    }
}

然后在第二个backgroundworker progresschanged

private void _FileCountingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (typeof(object[]) == e.UserState.GetType())
    {
        object[] StatusMsg = (object[])e.UserState;
        if (6 == StatusMsg.GetLength(0))
        {
            if (StatusMsg[5] != null)
            {
                lblCountingFiles.Text = StatusMsg[5].ToString();
            }
        }
    }
}

例外是在线:

lblCountingFiles.Text = StatusMsg[5].ToString();
  

跨线程操作无效:控制'lblCountingFiles'从其创建的线程以外的线程访问

我正在更新ProgressChanged事件中的标签。为什么我得到例外?
我该如何解决呢?

2 个答案:

答案 0 :(得分:2)

您正在_FileCountingWorker.RunWorkerAsync();从另一个DoWork主题调用BackgroundWorker。 因此,当_FileCountingWorker报告进度时,它不会回到UI线程,因为它不是从UI线程启动的。这就是你得到跨线程异常的原因。

尝试从UI线程或_FileCountingWorker.RunWorkerAsync()事件中调用_FileProcessingWorker_ProgressChanged

否则你可以使用:

private void _FileCountingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (!Dispatcher.CheckAccess()) // CheckAccess returns true if you're on the dispatcher thread
    {
        Dispatcher.Invoke(new Action<object, ProgressChangedEventArgs>(_FileCountingWorker_ProgressChanged), sender, e);
        return;
    }
    if (typeof(object[]) == e.UserState.GetType())
    {
        object[] StatusMsg = (object[])e.UserState;
        if (6 == StatusMsg.GetLength(0))
        {
            if (StatusMsg[5] != null)
            {
                lblCountingFiles.Text = StatusMsg[5].ToString();
            }
        }
    }
}

答案 1 :(得分:1)

我认为问题出在你拥有的主线上

object[] CurrentStatus;

在后台,您可以在报告进度到达之前对其进行新增 (或同时)

杀死上述
只需在do_work中创建对象

object[] CurrentStatus = new object[6];