2015-03-16 3 views
1

Я разработал клиент сокета async, после подключения я вызываю эту процедуру OnConnect.ошибка при вызове winform в процедуре onconnect

Цель состоит в том, чтобы установить текст состояния в главном окне на «подключен», а затем показать диалоговое окно входа в систему для пользователя

Friend Sub OnConnect(ByVal ar As IAsyncResult) 
     Try 
      oSocket.EndConnect(ar) 
      MainDialog.SetStatus("Connected") <-- this line is giving the error 

      'We are connected so start listening for messages 
      byteData = New Byte(1023) {} 
      'Start listening to the data asynchronously 
      oSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing) 
      '// show login dialog 
      loginDlg = New LoginDialog 
      loginDlg.ShowDialog() 
     Catch ex As Exception 
      ShowMessage(String.Format(My.Resources.error_failed_reason, "connect", "server", ex.Message), MessageBoxIcon.Information) 
     End Try 
    End Sub 

, но я получаю исключение

An возникла ошибка при создании формы. См. Exception.InnerException для . Ошибка: Текущий поток должен быть установлен на один поток (STA) до того, как вызовы OLE могут быть сделаны. Убедитесь, что ваша основная функция имеет отмеченный на ней STAThreadAttribute.

Я не использую любую тему, только асинхронное гнездо

, что может быть причиной этой ошибки? - это OnConnect, вызываемый в другом потоке?

EDIT

Я просто сделал свою заявку один поток, добавив этот

Public Class Program 
    <STAThread()> _ 
    Shared Sub Main() 
     Dim frm As New MainDialog 
     Application.Run(frm) 
    End Sub 
End Class 

EDIT 2

я заменил эту строку

MainDialog.SetStatus("Connected") 

С этой линией

If MainDialog.InvokeRequired Then <-- This line gives the same error as above 
    MainDialog.Invoke(New LoginDelegate(AddressOf ShowLogin), "Connected") 
End If 

Я создал этот делегат в модуле выше

Private Delegate Sub LoginDelegate(ByVal Item As Object) 
+0

На какой именно линии вы получаете исключение? – bokibeg

+1

в этой строке 'MainDialog.SetStatus (« Connected ») <- эта строка дает ошибку' – Smith

+0

Перечитываю вопрос сейчас, я пропустил его сначала :).Вам просто нужно установить атрибут 'STAThread', как предложил Lajos, и он должен работать нормально. Скажите нам, если это не решит проблему. Это может быть то, что событие запускается из другого потока, в этом случае вам нужен diff. решение. – bokibeg

ответ

0

Я был в состоянии решить мою проблему сам, то, что я сделал, переместили код в виде MainDialog.

Кажется maindialog.invoke не может быть вызван из другого потока другой, что UI нить

0

Вы должны использовать атрибут STAThread (далее here). Обратите внимание, что вы являются с помощью резьбы, основной темы. Если вы не использовали нить, вы не сможете запускать свою программу.

+0

Я сделал мое приложение одним потоком, добавив этот код в edit – Smith

+0

Проблема остается? –

+0

да, проверьте новое редактирование выше – Smith

2

Вы не должны обновлять пользовательский интерфейс в рабочем потоке. Ни MainDialog.SetStatus, ни loginDlg.ShowDialog - это правильная работа в рабочей нити.

В идеале вы должны называть его в потоке пользовательского интерфейса. Вы сделаете это, позвонив по номеру Control.Invoke или Control.BeginInvoke.

См How to update the GUI from another thread in C#?

+0

Я не использую нити вручную в своем приложении. – Smith

+0

@ Смит Это не имеет значения. В рабочий поток будет вызван обратный вызов асинхронного ввода-вывода. Он будет вызываться в потоке завершения ввода-вывода. Вам нужно передать элемент управления в поток пользовательского интерфейса через Control.Invoke или Control.BeginInvoke –

+0

@Smith Кажется, что событие запускается из другого потока, даже если это ** было ** STA, вы все равно получите исключение операции поперечного потока из-за отсутствия «BeginInvoke». – bokibeg

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