c# - 从 DoWork 处理程序调用方法?

标签 c# backgroundworker

我正在尝试使用 BackgroundWorker 来完成任务。我已经让工作人员正确运行,在 DoWork 方法下,它然后调用另一个执行的方法,但随后我面临我的问题:当该方法尝试调用另一个方法时,它不会成功并且不会抛出一个异常,我只能将其视为我在 BackgroundWorker 上做错的事情,因为在 UI 线程上运行以测试方法按预期执行时。

这是我运行我的工作人员的地方:

private void btnAddShots_Click(object sender, EventArgs e)
{
    backgroundWorker.RunWorkerAsync();     
}

这是我的 DoWork 方法:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int noOfShots = dataGridShots.Rows.Count - 1;
    int count = 0;

    while (count < noOfShots)
    {
        addTaskPair(dataGridShots.Rows[count].Cells[0].Value.ToString(), 
            dataGridShots.Rows[count].Cells[1].Value.ToString(), 
            dataGridShots.Rows[count].Cells[2].Value.ToString());

        count += 1;
    }
}

这是我的工作人员调用的 addTaskPair 方法的精简版本:

private void addTaskPair(string taskName, string taskDescription, string taskPriority)
{
    try
    {
        Task trackingTask = new Task();

        trackingTask.content = taskName;
        trackingTask.description = taskDescription;
        trackingTask.priority = taskPriority; 

        string trackingJson = JsonConvert.SerializeObject(trackingTask);
        trackingJson = "{ \"todo-item\":" + trackingJson + " }";

        string jsonResponse;
        jsonResponse = postJSON(trackingJson, teamworkURL + "/tasklists/" 
            + todoLists.todoLists[cmbTrackingList.SelectedIndex].id + "/tasks.json");
    }
    catch (Exception e)
    {
        debugMessage(e.ToString());
    }
}

在上面的示例中,您将看到我调用了方法 postJSON,这就是我碰壁的地方。通过测试,我已经验证上述方法可以运行,但是从该线程内调用 postJSON 方法时根本不运行。

在研究这个问题时,我看到了许多对 Invoking 的引用,但它们似乎都适用于更改我不需要做的 ui 控件(尽管进度条是使用 操纵的) ProgressChanged BackgroundWorker 事件)。

如果需要的话,我可以进一步澄清我的问题,但我真的希望得到这方面的帮助,因为我以前从未成功地使用过后台工作人员或线程(我不是专业人士,因为我确信你可以从我的代码中看出) .

最佳答案

您正在使用 BackgroundWorker.DoWork 事件处理程序中的 UI 控件。不要这样做。

在启动 BackgroundWorker 之前收集数据,并将其作为参数传递给 RunWorkerAsync 方法。不要从 BackgroundWorker.DoWork 触摸 UI - 通过 ReportProgress 方法更新进度就可以了。

此外,如果您在 .NET 4.5+ 上运行,您可能需要考虑使用新的 Task 模式。它仍然需要您预先收集要处理的数据,但使用起来要容易得多:

(编辑:正如Peter所建议的,无效访问发生在cmbTrackingList.SelectedIndex中;我已将其包含在下面的代码中。这正是我建议的原因对单独线程中发生的操作使用静态方法 - 它会让您更多地思考正在使用的数据)

var todoList = todoLists.todoLists[cmbTrackingList.SelectedIndex];

var data = 
  dataGridShots
  .Rows
  .Select
   (
     i => 
     new 
     { 
       TaskName = i.Cells[0].Value.ToString(), 
       TaskDescription = i.Cells[1].Value.ToString(), 
       TaskPriority = i.Cells[2].Value.ToString()
     }
   )
  .ToArray();

var result = 
   await Task.Run
   (
     () => 
     foreach (var row in data) 
       handleRowData(row.TaskName, row.TaskDescription, row.TaskPriority, todoList)
   );

现在您可能会注意到,让您的 postJson 方法异步也应该不会太难(有很多方法可以异步发出 HTTP 请求) - 这将允许您使整个代码异步而不阻塞任何线程。

多线程很难。始终尝试使用尽可能高的抽象,并避免任何共享状态。如果您确实需要共享状态,则需要同步每个线程对它的每次访问 - 尽量避免这种情况(一个好的做法是让方法在不同线程上执行静态,这样您就不会意外触及共享状态)。

关于c# - 从 DoWork 处理程序调用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29079330/

相关文章:

c# - 在 backgroundworker 运行时显示等待光标

c# - 如何使用MVVM/ICommand模式在WPF中正确实现BackgroundWorker

c# - 如何使用用户键入的关联显示文本获取 ComboBox 的值成员?

c# - CaSTLe 温莎依赖注入(inject) : Use the caller type as a parameter

java - cucumber ,所有场景重复登录步骤

c# - 替换字符串中的多个范围

android - 在 phonegap 中实现长时间运行的后台任务

c# - 调度程序的种类

C#,后台 worker 类

c# - 如何在 WPF 中手动触发 RelayCommand?