Почему Invoke через Delegate не встроен в .NET? - PullRequest
5 голосов
/ 01 сентября 2011

Я понимаю, что .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 ]

6 голосов
/ 01 сентября 2011

Это означало бы превращение каждой операции элемента управления пользовательского интерфейса в делегат, на тот случай, если его необходимо перенаправить в другой поток. Это было бы очень дорого. Кроме того, это предполагает, что вы всегда хотите делать одно и то же - используйте Invoke вместо BeginInvoke, например.

Я согласен, что немного неудобно делать это вручную, но следующие версии C # и VB должны облегчить жизнь с помощью асинхронных методов.

(Кроме того, я не думаю, что вы действительно хотите использовать ByRef для всех этих параметров ... неужели вы не совсем понимаете, что означает ByRef? )

1 голос
/ 01 сентября 2011

В конкретном случае с BackgroundWorker я бы посоветовал вам использовать его функцию отчетов о прогрессе.

Ваш BackgroundWorker вызывает ReportProgress, необязательно передавая объект с некоторой информацией о состоянии. Это вызывает событие ProgressChanged в потоке пользовательского интерфейса, которое может обновлять элементы управления в вашей форме, используя информацию о состоянии, передаваемую фоновым рабочим.

Отчет о прогрессе не ограничивается обновлением ProgressBar или аналогичного.

1 голос
/ 01 сентября 2011

Я не работаю на Microsoft, но, как я полагаю,

Большая часть кода GUI, написанного на .NET, не является многопоточной, поэтому зачем браться за проверку для случая меньшинства.Разработчик должен знать, что существует возможность многопоточности, и проверять при необходимости.

...