为什么不通过内置于.NET的Delegate调用

时间:2011-09-01 08:59:59

标签: c# .net vb.net delegates invoke

我理解.NET是多线程的,这是一件好事,但是当我有一个后台工作者时,我会不断遇到问题,例如我在表单上更新了一些控件,我必须这样做:

Private Sub SetRowCellBoolValueThreadSafe(ByVal row As Integer, ByVal col As Integer, ByVal value As Boolean)
    If dgvDatabase.InvokeRequired Then
        Dim d As New SetRowCellBoolValueCallback(AddressOf SetRowCellBoolValue)
        Me.Invoke(d, New Object() {row, col, value})
    Else
        SetRowCellBoolValue(row, col, value)
    End If
End Sub

Delegate Sub SetRowCellBoolValueCallback(ByVal row As Integer, ByVal col As Integer, ByVal value As Boolean)

Private Sub SetRowCellBoolValue(ByVal row As Integer, ByVal col As Integer, ByVal value As Boolean)
    dgvDatabase.Rows(row).Cells(col).Value = value
End Sub

我的问题是为什么这没有内置到框架中 - 当然如果我正在尝试更新DataGridView它应该足够聪明,知道更新何时来自另一个线程并且它可以完成上述所有操作?

3 个答案:

答案 0 :(得分:6)

这意味着将 UI控件上的每个操作转换为委托,以防万一需要编组到另一个线程。那将是非常昂贵的。此外,它预先假定您总是希望做同样的事情 - 例如使用Invoke而不是BeginInvoke

我同意手动执行此操作有点痛苦,但是使用异步方法,C#和VB的下一个版本应该会让生活变得更轻松。

(顺便说一下,我不认为你真的想要使用ByRef来表示所有这些参数...你有可能不清楚{{1} 1}}表示?)

答案 1 :(得分:1)

我不为微软工作,但我猜,

用.NET编写的大多数GUI代码都不是多线程的,因此,为什么要承担检查少数情况的负担。开发人员应该知道它有可能进行多线程并在适当的时候进行检查。

答案 2 :(得分:1)

在BackgroundWorker的特定情况下,我建议您使用其进度报告功能。

您的BackgroundWorker调用ReportProgress,可选地传递带有某些状态信息的对象。这会在UI线程上引发ProgressChanged事件,该事件可以使用从后台工作程序传递的状态信息更新表单上的控件。

进度报告不仅限于更新ProgressBar或类似内容。