在单独的线程中启动WPF窗口

3
我正在使用以下代码打开一个在单独线程中的窗口。
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Thread newWindowThread = new Thread(new ThreadStart(() =>
        {
            // Create and show the Window
            Config tempWindow = new Config();
            tempWindow.Show();
            // Start the Dispatcher Processing
            System.Windows.Threading.Dispatcher.Run();
        }));

        // Set the apartment state
        newWindowThread.SetApartmentState(ApartmentState.STA);
        // Make the thread a background thread
        newWindowThread.IsBackground = true;
        // Start the thread
    }
}

如果我将这段代码放在一个方法中,它是有效的。但是当我按照以下方式使用它时,会出现错误:

public partial class App : Application
{
    #region Instance Variables
    private Thread newWindowThread;

    #endregion

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        newWindowThread = new Thread(new ThreadStart(() =>
        {
            // Create and show the Window
            Config tempWindow = new Config();
            tempWindow.Show();
            // Start the Dispatcher Processing
            System.Windows.Threading.Dispatcher.Run();
        }));
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        // Set the apartment state
        newWindowThread.SetApartmentState(ApartmentState.STA);
        // Make the thread a background thread
        newWindowThread.IsBackground = true;
        // Start the thread
    }
}

它会抛出以下错误:
System.Threading.ThreadStateException
The state of the thread was not valid to execute the operation

这是什么原因导致的?


你只点击了一次吗?(线程不能启动两次) - Olivier
3个回答

2

@d.moncada, @JPVenson, @TomTom,对不起,尤其是@d.moncada,您的回答让我意识到了我的真正错误,确实只需要运行一次直到代码运行。但我的真正问题是,我尝试在两个位置中点击button1_Click,我使用了一个被称为的定时器,它调用了一行代码。

 private void button1_Click(object sender, RoutedEventArgs e)

现在我的问题的解决方案是如何检测C# .net中是否有线程正在运行?


1
我认为问题在于您在线程已经开始运行后设置了ApartmentState
请尝试:
public partial class App : Application
{
    #region Instance Variables
    private Thread newWindowThread;

    #endregion

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        newWindowThread = new Thread(new Thread(() =>
        {
            // Create and show the Window
            Config tempWindow = new Config();
            tempWindow.Show();
            // Start the Dispatcher Processing
            System.Windows.Threading.Dispatcher.Run();
        }));
        // Set the apartment state
        newWindowThread.SetApartmentState(ApartmentState.STA);
        // Make the thread a background thread
        newWindowThread.IsBackground = true;
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        // Start the thread
        newWindowThread.Start();
    }
}

-4
为什么你要这样做?在应用程序中运行第二个UI线程几乎没有理由...如果你想要一个非模态的新窗口,请实例化你的窗口并调用show
为什么说几乎没有理由?因为这是一个非常复杂的话题,除非你有巨大的预算来开发这种行为,否则你可以不用它。

7
-1. “NO REASON?”你见过一个金融交易应用程序在6个屏幕上运行吗?每个窗口都有一个独立的消息泵(message pump)真是太棒了。将不同的窗口放在不同的线程中的好处是,“UI是单线程”的原则适用于每个窗口,这可以帮助实现很多并行化处理。所以说,确实存在理由——虽然这些理由比较特殊,我承认它们并不适用于大多数程序,但是有些人可能正是需要这种做法的人。“绝大多数人甚至不知道这是可能的。” - TomTom
1
只是一个“技能”问题...我在一家处理吉字节数据的公司工作,但只有两个非常复杂的Windows,而且所有东西都处于非常高的性能水平(使用Thredding,但不像“把所有东西放入线程中并感到满意”^^)。如果您的应用程序真的需要为每个单独的UI渲染创建一个线程,那么您可能需要重新考虑/重构您的软件设计。如果您需要复杂的UI渲染,则可以在线程中创建/修改数据,然后让UI进行渲染。90%的情况下,有比仅将事物放入线程中更好的方法。 - Venson
1
@JPVenson:嗯,你可以建议Chrome开发团队重构他们的代码... Chrome不仅在UI上使用一个线程,而且在UI上使用一个进程。依赖于其他人的代码良好行为并不真正健壮也不可持续。除非你公司里每个人都是一个非常优秀的程序员 :) - Olivier
1
@JPVenson:我不知道Guillermo的应用程序大小,但如果UI渲染良好且将来不会出现问题,则没有理由为UI运行STA,所以我同意你的观点。但是,如果UI存在性能问题(虽然我怀疑),那么您可以使用STA线程。因此,我认为人们只是从其他网站复制代码并编写类似的应用程序。 - Bura Chuhadar
我认为如果微软在他们的文档中选择解释如何实现这一点,那么说明这个需求被认为是足够重要的。(请参见“多窗口、多线程”部分)https://msdn.microsoft.com/library/ms741870(v=vs.100).aspx - Holf
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接