문제

공유 클래스를 사용하여 응용 프로그램의 모든 공통 개체를 수용하는 Windows 양식 응용 프로그램이 있습니다. 설정 클래스에는 정기적으로 일을하는 객체 모음이 있으며 관심있는 것이 있으므로 기본 양식에 경고하고 업데이트해야합니다.

나는 현재 객체의 이벤트를 통해이 작업을 수행하고 있으며 각 객체가 만들어지면 이벤트 핸들러를 추가하여 이벤트를 양식에 다시 맵핑합니다. 그러나 저는 이러한 요청이 항상 내 양식의 메인 사본에 끝나는 것은 아닙니다. 예를 들어, 내 양식에는 알림 트레이 아이콘이 있지만 양식이 캡처하고 이벤트를 표시하고 기포를 표시하려고 시도하면 거품이 나타나지 않습니다. 그러나 해당 코드를 수정하여 아이콘을 보이게 만들고 (이미 있지만) 버블을 표시하면 두 번째 아이콘이 나타나서 버블을 올바르게 표시합니다.

아무도 전에 이것에 빠진 사람이 있습니까? 양식의 단일 인스턴스로 모든 이벤트를 캡처하도록 강요 할 수있는 방법이 있습니까, 아니면이를 처리 할 수있는 완전히 다른 방법이 있습니까? 필요한 경우 코드 샘플을 게시 할 수 있지만 일반적인 스레딩 문제라고 생각합니다.

추가 정보: 현재 저를 사용하고 있습니다. invokerequired에서 내 양식의 이벤트 핸들러에서 항상이 경우 거짓을 반환합니다. 또한이 양식에서 볼 때 생성 된 두 번째 트레이 아이콘에는 컨텍스트 메뉴가 없지만 "실제"아이콘은 그렇습니다.

나는 내 머리카락을 꺼내겠다! 이것은 그렇게 어려울 수 없습니다!

해결책: 단서에 대한 Nobugz에게 감사의 말을 전하며, 지금 사용하고있는 코드로 이끌었습니다 (아름답게 작동하지만 더 좋은 방법이 있다고 생각할 수는 없습니다). 개인 부울 변수를 "isprimary"라는 형식에 추가하고 다음 코드를 양식 생성자에 추가했습니다.

    Public Sub New()
        If My.Application.OpenForms(0).Equals(Me) Then
            Me.IsFirstForm = True
        End If
    End Sub

이 변수가 설정되고 생성자가 완료되면 이벤트 핸들러로 바로 향하고 이런 식으로 처리합니다 (경고 : 내가 찾고있는 양식이 응용 프로그램의 기본 형식이기 때문에 my.application.openforms ( 0) 내가 필요한 것을 얻습니다. 제가 비 시작 양식의 첫 번째 인스턴스를 찾고 있다면, 내가 찾을 때까지 반복해야 할 것입니다) :

    Public Sub EventHandler()
        If Not IsFirstForm Then
            Dim f As Form1 = My.Application.OpenForms(0)
            f.EventHandler()
            Me.Close()
        ElseIf InvokeRequired Then
            Me.Invoke(New HandlerDelegate(AddressOf EventHandler))
        Else
            ' Do your event handling code '
        End If
    End Sub

먼저 올바른 양식으로 실행되는지 확인합니다. 그렇지 않은 경우 올바른 양식을 호출하십시오. 그런 다음 스레드가 올바른지 확인하고 UI 스레드가 그렇지 않은 경우 호출합니다. 그런 다음 이벤트 코드를 실행합니다. 나는 그것이 잠재적으로 세 번의 전화라는 것을 좋아하지 않지만 다른 방법을 생각할 수는 없습니다. 조금 번거 롭지 만 잘 작동하는 것 같습니다. 누구든지 더 나은 방법이 있다면 듣고 싶습니다!

다시 한 번, 모든 도움에 감사드립니다 - 이것은 나를 미쳤다!

도움이 되었습니까?

해결책

나는 그것이 스레딩 문제라고 생각합니다. 이벤트 핸들러에서 control.invoke ()를 사용하고 있습니까? .NET은 일반적으로 앱을 디버깅 할 때 위반을 포착하지만 할 수없는 경우가 있습니다. Notifyicon은 그중 하나이며 스레드 친화력을 확인할 창 핸들이 없습니다.

OP가 변경된 후 편집 : 질문 :

클래식 vb.net 트랩은 형식 인스턴스를 유형 이름으로 참조하는 것입니다. form1.notifyicon1.something. 스레딩을 사용할 때는 예상대로 작동하지 않습니다. 그것은 a를 만들 것입니다 새로운 form1 클래스의 인스턴스는 기존 인스턴스를 사용하지 않습니다. 이 인스턴스는 보이지 않으며 (show ()는 호출되지 않았으며, 메시지 루프를 펌핑하지 않는 스레드에서 실행되기 때문에 Doornail으로 죽었습니다. 두 번째 아이콘이 나타나는 것은 죽은 자식입니다. 스레드에서 사용하고 있다는 것을 알면 revokequired = false가 있습니다.

기존 양식 인스턴스에 대한 참조를 사용해야합니다. 그것이 오기가 어렵다면 (일반적으로 "나"를 클래스 생성자에게 인수로 전달) 응용 프로그램을 사용할 수 있습니다.

  Dim main As Form1 = CType(Application.OpenForms(0), Form1)
  if (main.InvokeRequired)
    ' etc...

다른 팁

컨트롤을 사용하여 적절한 스레드에 있는지 확인한 다음 Control.invoke를 사용하지 않으면 컨트롤을 사용하십시오.

양식의 호출 메소드에 대한 문서를 살펴 봐야합니다. 이를 통해 양식을 소유 한 스레드에서 실행되는 양식을 업데이트하는 코드를 만들 수 있습니다 (Windows 양식은 스레드 안전하지 않음). 개인 대표 하위 Sub updatesTestAtusDelegate와 같은 것 (byval newstatus as string)

public sub updatestatus (byval newstatus as string) me.invokerequired 다음에 dim d dim d as updatestatusdelegate (addrendef updatestatus) me.invoke (d, new object () {newstatus}) else '양식 상태 종료 if를 업데이트합니다.

샘플 코드를 제공하면 더 맞춤형 예제를 제공하게되어 기쁩니다.

OP 이후의 편집은 vokeRequired를 사용하고 있다고 말했다.

invokerequired를 호출하기 전에 양식 핸들이 생성되었는지 확인하고, 내가 신뢰하는 핸드 레피트 속성이 있는지 확인하십시오. 컨트롤에 핸들이 없으면 항상 invokerequired는 항상 false를 반환합니다. 그러면 올바른 일을했지만 코드가 스레드 안전하지 않음을 의미합니다. 알 때 질문을 업데이트하십시오. 일부 샘플 코드도 도움이 될 것입니다.

C#에서는 다음과 같습니다.

private EventHandler StatusHandler = new EventHandler(eventHandlerCode)
void eventHandlerCode(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(StatusHandler, sender, e);
        }
        else
        {
          //do work
        }
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top