1

제 3 자 라이브러리를 사용하여 타사 입력 장치에서 Windows Form으로 데이터를 전달하고 있습니다. 내가 뭘 찾고있는 장치에서 입력 데이터를 수집하고, 처리하고 특정 상황에 윈도우 UI 스레드가 무슨 일이 일어나고 있는지 주어진다. 제 3 자 DLL의 소스 코드에 액세스 할 수 없지만 기본 방법이 백그라운드 프로세스에 있다는 것을 알고 있으며 작성하지 않았기 때문에 생각한 기본 UI 스레드로 내 결과를 다시 전달할 수 없습니까?작업자 스레드를 사용하는 다중 스레드 라이브러리가 UI 스레드와 통신 할 수 없습니다. 스레드

윈도우 형태 :

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     // create instance of my listener 
     MyListener listener = new MyListener(this); 
     Controller controller = new Controller(listener); 
    } 
} 
제 3 자 클래스 리스너를 확장

위한 MyListener 등급 :

public class MyListener : Listener 
{ 
    public Form1 form; 
    private Frame frame; 

    // overloaded constructor 
    public LeapListener(Form1 f) 
    { 
     form = f; 
    } 

    /// <summary> 
    /// onFrame is the main method that runs every milisecond to gather relevant information 
    /// </summary> 
    public override void onFrame(Controller controller) 
    { 
     // Get the most recent frame and report some basic information 
     frame = controller.frame(); 
    } 
} 

문제는 내가에 myListener 클래스 내에서 어디에서 메인 UI 스레드에 다시 통신 할 수 있지만 배경 스레드에서 실행 중이므로 onFrame 메서드에서 다시 통신 할 수 없습니다. 어쨌든 내가 만들지 않은 백그라운드 스레드에서 주 스레드를 잡아 둘 수 있습니까?

ReportProgress를 시도했습니다. MyListener에서 이벤트를 만들려고 시도했으며 onFrame의 기본 UI 스레드와 대화를 시도하여 응용 프로그램을 중단하고 잘못된 메모리 위치 오류를 제공하려고 시도했습니다.

도움을 주시면 감사하겠습니다.

+0

'생성하지 않은 백그라운드 스레드에서 주 스레드를 보류 할 수 있습니까?' 확실히, 현저한 문제는 C++/C#/무엇이든지 그것을 할 수있는 것입니다. 일반적으로 이것은 언어/라이브러리에서 제공하는 Invoke/BeginInvoke 메서드 또는 SendMessage/PostMessage API입니다. 나왔어? –

+0

'컨트롤러'는 다른 스레드에서 실행되는 객체입니까? – didierc

답변

0

일반적으로 UI를 처리하는 스레드가 아닌 다른 스레드에서 UI 개체에 액세스하려고하면 문제가 발생합니다. 이것은 창문 만의 문제는 아니지만보다 일반적인 패턴입니다.

일반적인 해결책은 UI를 업데이트하는 데 필요한 데이터가 포함될 이벤트 전파 메커니즘의 일부 형식을 설정하고 주 스레드가 해당 작업을 처리하도록하는 것입니다.

UI 스레드 UI 및 백그라운드 스레드 BT를 호출 해 보겠습니다.

이벤트를 BT에서 UI로 게시 한 다음 이벤트가 UI에 의해 처리 될 때까지 BT를 차단하는 기능을 가질 수 있습니다. UI가 그것을 해제 할 때까지 BT를 차단하기 위해 세마포어를 사용하는 간단한 시스템입니다. 이러한 시스템의 장점은 간단하기 때문에 두 스레드 중 한 번에 둘 이상의 이벤트를 처리 할 필요가 없다는 것입니다. 단점은 이벤트가 처리되는 데 오랜 시간이 걸리면 애플리케이션의 샘플링 해상도가 매우 낮아진다는 것입니다. 대체 방법 (그리고 더 나은 방법)은 이벤트 큐를 생성하고, BT 게시를하고, UI를 폴링하여 업데이트합니다. 좀 더 많은 작업이 필요하지만 UI 긴 타이밍에보다 탄력적입니다.

두 번째 기술의 경우 이벤트 형식을 설정하고 BT와 UI간에 공유 및 뮤텍스 보호 대기열을 설정해야하며 나머지는 쉽게 수행 할 수 있어야합니다.

큐는 다음과 같이 될 수있다 :

#include <queue> 


template <typename EVENT> 
class EventQueue { 
    protected: 
    typedef EventQueue<EVENT> self_type; 
    typedef std::queue<EVENT> queue_type; 
    Mutex m_; 
    queue_type q_; 
    void lock(){ 
     // lock the mutex 
    } 
    void unlock(){ 
     // unlock the mutex 
    } 
    public: 
    EventQueue() { 
     // initialize mutex 
    } 
    ~EventQueue() { 
     // destroy mutex 
    } 

    void push(EVENT &e){ 
     lock(); 
     q_.push(e); 
     unlock(); 
    } 
    EVENT &pop(){ 
     EVENT &e; 
     lock(); 
     e = q_.pop(); 
     unlock(); 
     return e; 
    } 
    int size(){ 
     int i; 
     lock(); 
     i = q_.size(); 
     unlock(); 
     return i; 
    } 
}; 

이것은 당신이 볼 수있는 매우 간단합니다, 당신은 단지 당신이 필요로하는 어떤 이벤트 클래스와 위의 템플릿을 사용한다.

뮤텍스를 처리하는 코드를 생략했습니다. 의존 할 API에 달려 있습니다. 위에서 설명한 것처럼 UI는 대기열을 폴링해야합니다. 즉, 대기열의 크기를 확인하고 사용할 수있는 경우 이벤트를 꺼내야합니다. BT 측에서는 폼에 직접 액세스하는 대신 MyListener 클래스에 이벤트 푸시 콜을 포함하기 만하면됩니다.

이 방법은 서로의 발가락을 밟지 않고 두 스레드를 함께 작동시키는 데 매우 효과적입니다.

관련 문제