我正在尝试使用 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/