2010-03-23 2 views
1

Я пытаюсь написать альтернативу VB.NET для анонимной функции C#.Делегат в делегате в VB.NET

Я хочу вызвать Threading.SynchronizationContext.Current.Send, который ожидает, что ему будет передан делегат типа Threading.SendOrPostCallback. Фон here, но поскольку я хочу, чтобы оба передавали строку в MessageBox.Show, а также захватили DialogResult, мне нужно определить другой делегат внутри. Я борюсь с синтаксисом VB.NET, как из традиционного стиля делегата, так и из лямбда-функций.

Мой идти в традиционном синтаксисе ниже, но я кишка чувство, что это должно быть намного проще, чем это:

Private Sub CollectMesssageBoxResultFromUserAsDelegate(ByVal messageToShow As String, ByRef wasCanceled As Boolean) 
    wasCanceled = False 
    If Windows.Forms.MessageBox.Show(String.Format("{0}{1}Please press [OK] to ignore this error and continue, or [Cancel] to stop here.", messageToShow), "Continue", Windows.Forms.MessageBoxButtons.OKCancel, Windows.Forms.MessageBoxIcon.Exclamation) = Windows.Forms.DialogResult.Cancel Then 
     wasCanceled = True 
    End If 
End Sub 


Private Delegate Sub ShowMessageBox(ByVal messageToShow As String, ByRef canceled As Boolean) 


Private Sub AskUserWhetherToCancel(ByVal message As String, ByVal args As CancelEventArgs) 

    If args Is Nothing Then args = New System.ComponentModel.CancelEventArgs With {.Cancel = False} 

    Dim wasCancelClicked As Boolean 
    Dim firstDelegate As New ShowMessageBox(AddressOf CollectMesssageBoxResultFromUserAsDelegate) 
    '…. Now what?? 
    'I can’t declare SendOrPostCallback as below: 
    'Dim myDelegate As New Threading.SendOrPostCallback(AddressOf firstDelegate) 


End Sub 

ответ

4

Я думаю, что самый простой способ справиться с этим, чтобы создать новый объект, который оборачивает отображение окна сообщения. Затем этот объект можно использовать для получения результата.

Например:

Public Class Helper 
    Public WasCanceled as Boolean 
    Public Message As String 
    Public Done as New ManualResetEvent(false) 
    Public Sub New(message as String) 
    Me.Message = message 
    End Sub 
    Public Sub ShowMessageBox(unused as Object) 
    If MessageBox.Show(Message) = DialogResult.Cancel Then 
     WasCanceled = True 
    Done.Set() 
    End Sub 
End Class 

Public Sub AskUserWhetherToCancel(context as SynchronizationContext, message As String) 
    Dim helper As New Helper(message) 
    context.Post(AddressOf helper.ShowMessageBox, Nothing) 

    ' Wait for it to finish 
    helper.WaitOne() 

    if helper.WasCanceled Then 
    ... 
    Else 
    ... 
    End IF 
End Sub 
+0

Великий, Благодаря Джареду это сработало хорошо. Я схватил SynchronizationContext формы в конструкторе формы и использовал это как контекст для Post to. Мне не нужно было WaitOne или использовать ManualResetEvent, потому что я делал Post (синхронно), а не Send (async). Дополнительные ссылки на SynchronizationContext: http://blogs.msdn.com/mattdotson/archive/2006/02/13/531315.aspx и http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx – Topdown

1

Попробуйте это:

Dim myDelegate As New Threading.SendOrPostCallback(Function(c) firstDelegate) 

Не уверен, что если он будет работать как вам угодно, но он скомпилируется.

Возможно, это то, что вы ищете: Passing parameters to delegates in VB.NET

+0

Правильно, он будет компилировать сам по себе, но как я нажимаю Params (сообщение, wasCancelClicked) в этом. И тогда, как бы я называю: Threading.SynchronizationContext.Current.Send (AddressOf myDelegate) Если я что я получаю сообщение об ошибке: «Операнд„AddressOf“должно быть имя метода (без скобок)» – Topdown

Смежные вопросы