【问题标题】:Creating a window from a new thread in WPF app with no main window在没有主窗口的 WPF 应用程序中从新线程创建窗口
【发布时间】:2011-11-12 05:23:03
【问题描述】:

我正在开发一个没有主窗口的 WPF 应用程序(它使用来自 http://www.codeproject.com/KB/WPF/wpf_notifyicon.aspx 的代码在通知区域中运行)。

在 App.xaml.cs 中,我创建了一个新线程,该线程运行一些返回自定义警报集合的监控代码。该集合有一个 render() 方法,我计划用它来显示一个包含警报信息的窗口,但我不知道如何完成它。如有任何意见,我将不胜感激。

以下代码示例:

App.xaml:

<Application x:Class="DowntimeReportMonitor.Views.Icon.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Startup="Application_Startup"
         Exit="Application_Exit">
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="IconDictionary.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
</Application>

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading;
using System.Windows;

using Hardcodet.Wpf.TaskbarNotification;

using DowntimeReportMonitor.Core;

namespace DowntimeReportMonitor.Views.Icon
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    private TaskbarIcon _taskbaricon;

    private AlertWorker _alertWorker;
    private Thread _alertWorkerThread;

    /// <summary>
    /// Event handler for Application startup
    /// </summary>
    /// <param name="sender">The event sender</param>
    /// <param name="e">Event arguments</param>
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        // Create and start a new TaskbarIcon.
        this._taskbaricon = (TaskbarIcon)FindResource("notificationIcon");

        // Create and start a new AlertWorker.
        this._alertWorker = new AlertWorker();
        this._alertWorkerThread = new Thread(this._alertWorker.doWork);
        this._alertWorkerThread.SetApartmentState(ApartmentState.STA);
        this._alertWorkerThread.Start();
    }



    /// <summary>
    /// Event handler for Application exit
    /// </summary>
    /// <param name="sender">The event sender</param>
    /// <param name="e">Event arguments</param>
    private void Application_Exit(object sender, ExitEventArgs e)
    {
        // Stop the alert worker.
        this._alertWorker.requestStop();
        this._alertWorkerThread.Join();

        // Dispose of the notification icon.
        this._taskbaricon.Dispose();
    }
}
}

AlertWorker.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using DowntimeReportMonitor.Core;

namespace DowntimeReportMonitor.Views.Icon
{
class AlertWorker
{
    private volatile bool _stopRequested;

    private ReportMonitor _reportMonitor;

    public AlertWorker()
    {
        _reportMonitor = new ReportMonitor(new wpfRenderableReportAlertCollection());
    }

    public void doWork()
    {
        while (!_stopRequested)
        {
            this._reportMonitor.monitorReports().render();

            Thread.Sleep(30000);
        }
    }

    public void requestStop()
    {
        this._stopRequested = true;
    }
}
}

【问题讨论】:

    标签: c# wpf user-interface systray windowless


    【解决方案1】:

    首先,您需要一个专用的 UI 线程。通常它是初始应用程序线程,但您可以使用任何线程。 (必须是 STA 线程。)

    接下来,您在该线程中启动一个 dispather (Dispatcher.CurrentDispatcher.Run)。

    接下来,您可以使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 向该线程发布命令。

    最后,您可以为您的自定义 Window 类发布到您的线程 window.Show

    【讨论】:

    • 我听从了您的建议,似乎成功了。缺少的一件事是我必须将对调度程序(this.dispatcher)的引用传递给后台线程。另外......一旦新窗口关闭,它就会退出整个应用程序。我仍在努力解决这个问题。
    • @bshacklett:嗯,对于第一个问题,您可以将调度程序保存在静态全局变量中,无论如何它是一个单例。对于退出的问题,你应该看看你的设置:(1)检查你的应用程序有shutdown mode不是“在主窗口关闭时”? (2) 检查您的工作线程是否不是后台线程(后台线程不会使应用程序保持活动状态)。
    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    相关资源
    最近更新 更多