为什么 .NET 中没有内置通过 Delegate 调用
我知道 .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 ,它应该足够智能,可以知道更新何时来自另一个线程,并且它可以自己完成上述所有操作?
I understand that .NET is multi-threaded and that is a good thing, but I continually run into issues when I have a background worker for example that is updating some control on my form and I have to do:
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
My question is why is this not built into the framework - surely if I am trying to update a DataGridView
it should be intelligent enough to know when the update is from another thread and it could do all the above itself?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这意味着将 UI 控件上的每个操作都转变为委托,以防万一需要将其编组到不同的线程。那将是非常昂贵的。此外,它假定您总是想要做同样的事情 - 例如,使用
Invoke
而不是BeginInvoke
。我同意手动执行此操作有点麻烦,但 C# 和 VB 的下一个版本应该会让异步方法的使用变得更加轻松。
(顺便说一句,我认为您真的不想对所有这些参数使用
ByRef
...您是否不太清楚ByRef
意味着什么?)The would mean turning every operation on a UI control into a delegate, just in case it needed to be marshalled to a different thread. That would be hugely expensive. Additionally, it presupposes that you always want to do the same thing - use
Invoke
rather thanBeginInvoke
for example.I agree it's a bit of a pain in the neck to have to do this manually, but the next versions of C# and VB should make life a lot easier with async methods.
(As an aside, I don't think you really want to use
ByRef
for all those parameters... is it possible that you're not really clear whatByRef
means?)我不在 Microsoft 工作,但我猜想,
大多数用 .NET 编写的 GUI 代码都不是多线程的,所以为什么要承担检查少数情况的负担。开发人员应该知道存在多线程的潜力,并在适当的时候进行检查。
I don't work for Microsoft but I would guess,
Most GUI code written with .NET is not Multi-threaded so, why incur the burden of checking for the minority case. The developer should know it there is a potential for multi-threading and check when appropriate.
在BackgroundWorker的具体情况下,我建议您使用它的进度报告功能。
您的BackgroundWorker 调用
ReportProgress
,可以选择传递带有某些状态信息的对象。这会在 UI 线程上引发ProgressChanged
事件,该事件可以使用从后台工作人员传递的状态信息来更新表单上的控件。进度报告不限于更新 ProgressBar 或类似内容。
In the specific case of a BackgroundWorker, I would suggest you use its progress reporting feature.
Your BackgroundWorker calls
ReportProgress
, optionally passing an object with some state information. This raises theProgressChanged
event on the UI thread, which can update controls on your form, using the state information passed from the background worker.Progress reporting is not limited to updating a ProgressBar or similar.