programing

STA 스레드에서 무언가를 실행하는 방법은 무엇입니까?

sourcejob 2023. 4. 29. 09:13
반응형

STA 스레드에서 무언가를 실행하는 방법은 무엇입니까?

WPF 애플리케이션에서 (서버와) 비동기 통신을 수행합니다.콜백 함수에서는 서버의 결과로부터 InkPresenter 개체를 생성하게 됩니다.이렇게 하려면 실행 중인 스레드가 STA여야 하지만 현재는 그렇지 않습니다.따라서 다음과 같은 예외가 발생합니다.

어셈블리에 정의된 'InkPresenter' 인스턴스를 만들 수 없습니다 [...] 많은 UI 구성 요소에서 이 인스턴스가 필요하므로 호출 스레드는 STA여야 합니다.

현재 내 비동기 함수 호출은 다음과 같습니다.

public void SearchForFooAsync(string searchString)
{
    var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
    caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
}

InkPresenter 생성을 수행할 콜백을 STA로 만들려면 어떻게 해야 합니까?또는 새 STA 스레드에서 XamlReader 구문 분석을 호출합니다.

public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    var foo = GetFooFromAsyncResult(ar); 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA
    [..]
}

다음과 같이 STA 스레드를 시작할 수 있습니다.

    Thread thread = new Thread(MethodWhichRequiresSTA);
    thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
    thread.Start(); 
    thread.Join(); //Wait for the thread to end

유일한 문제는 결과 객체가 어떻게든 전달되어야 한다는 것입니다.이에 대해 전용 필드를 사용하거나 매개 변수를 스레드로 전달하는 작업을 수행할 수 있습니다.여기서 개인 필드에 foo 데이터를 설정하고 STA 스레드를 시작하여 잉크 프레젠터를 변형시킵니다!

private var foo;
public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    foo = GetFooFromAsyncResult(ar); 
    Thread thread = new Thread(ProcessInkPresenter);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join(); 
}

private void ProcessInkPresenter()
{
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
}

이것이 도움이 되길 바랍니다!

Dispatcher 클래스를 사용하여 UI-Thread에서 메서드 호출을 실행할 수 있습니다.Dispatcher는 정적 속성 CurrentDispatcher를 제공하여 스레드의 Dispatcher를 가져옵니다.

InkPresenter를 만드는 클래스의 개체가 UI-Thread에 생성된 경우 CurrentDispatcher 메서드는 UI-Thread의 Dispatcher를 반환합니다.

디스패처에서 Begin을 호출할 수 있습니다.스레드에서 지정된 대리자를 비동기식으로 호출하는 호출 방법입니다.

UI 스레드에서 호출하기에 충분할 것입니다.따라서 다음을 사용합니다.BackgroundWorker그리고 위에RunWorkerAsyncCompleted그런 다음 잉크 프레젠터를 만들 수 있습니다.

다음을 사용하여 STA 스레드에서 클립보드 내용을 가져왔습니다.미래에 누군가를 돕기 위해 글을 올릴 생각이었는데...

string clipContent = null;
Thread t = new Thread(
    () =>
    {
        clipContent = Clipboard.GetText();
    });
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();

// do stuff with clipContent

t.Abort();

약간 해킹이긴 하지만 XTATestRunner를 사용하면 코드가 다음과 같이 표시됩니다.

    public void SearchForFooAsync(string searchString)
    {
        var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
        caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
    }

    public void SearchForFooCallbackMethod(IAsyncResult ar)
    {
        var foo = GetFooFromAsyncResult(ar); 
        InkPresenter inkPresenter;
        new XTATestRunner().RunSTA(() => {
            inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
        });
    }

추가로 다음과 같은 STA(또는 MTA) 스레드에 던져진 예외를 포착할 수 있습니다.

try
{
    new XTATestRunner().RunSTA(() => {
        throw new InvalidOperationException();
    });
}
catch (InvalidOperationException ex)
{
}

언급URL : https://stackoverflow.com/questions/2378016/how-to-run-something-in-the-sta-thread

반응형