C# Top-level Statements WPF 실행 방법?

안녕하세요. :smile:

C# 9.0 기능인 Top-level Statements에 대해 알아보고 있는데요.

혹시 WPF도 실행할 수 있을까요?


Console의 경우에는 잘 동작하는 것을 확인했습니다.

using System;

Console.WriteLine("Hello");
Console.WriteLine(args);

그래서 이와 비슷하게 WPF도 응용해보았습니다.

using System;

Application app = new Application();
app.Startup += (s, e) => new Window().Show();
app.Run();

앱을 실행하면 [STAThread] 관련 에러가 납니다.

많은 UI 구성 요소에서 호출 스레드가 필요하므로…


그래서 [STAThread]도 추가해봤습니다.

using System;

[STAThread]
void WpfStart()
{
    Application app = new Application();
    app.Startup += (s, e) => new Window().Show();
    app.Run();
}
WpfStart();

이렇게도 해봤지만 동일한 에러가 발생됩니다.

혹시 제가 잘못 사용한 부분이 있을까요? 그리고 이 기능이 어떤 의도로 사용되야 하는지도 궁금합니다!

읽어주셔서 감사합니다.

2개의 좋아요

Top-level Statements는 attribute를 쓸 수 없는 것으로 확인됩니다. TLS는 처음 C# 을 접하는 사람이 언어를 접근하기 쉽게 하기 위한 목적이 있어서 그런것 같습니다.

2개의 좋아요

어쩔 수 없습니다. 직접 해줘야죠. ^^; 아래의 글에 관련 답변이 있습니다.

[c# 9.0 - How to handle {STAThread] in C# 9 Using Top-Level Program.cs - Stack Overflow](c# 9.0 - How to handle {STAThread] in C# 9 Using Top-Level Program.cs - Stack Overflow)

혹은 좀 더 복잡하지만 아래의 글에 있는 StartSTATask 메서드를 이용해,

c# - Set ApartmentState on a Task - Stack Overflow

다음과 같은 식으로 코딩하면 됩니다.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

await StartSTATask(() =>
{
    Application app = new Application();
    app.Startup += (s, e) => new Window().Show();
    app.Run();

    return 0;
});

static Task<T> StartSTATask<T>(Func<T> func)
{
    var tcs = new TaskCompletionSource<T>();
    Thread thread = new Thread(() =>
    {
        try
        {
            tcs.SetResult(func());
        }
        catch (Exception e)
        {
            tcs.SetException(e);
        }
    });

    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    return tcs.Task;
}
4개의 좋아요

비슷한 이유로 Windows Forms 애플리케이션도 TLP 기능으로 코드를 시작할 수 없고, 앞의 분들이 답글을 달아주신 것처럼 workaround를 입혀야 하는데 “굳이?” 싶은 부분이 생기는 것 같아요. ㅎㅎ

2개의 좋아요

아, 그리고 이제 WPF에 관련된 내용은 윈도우 데스크톱 Q&A 쪽으로 올려주시면 더 좋을 것 같습니다! @jamesnet214

2개의 좋아요
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);

를 통해 최상위문에서 [STAThread] 효과를 줄 수 있다고 합니다… 음 확인해봤더니 되네요.

2개의 좋아요