我知道通常不应该从UI线程以外的线程触摸UI元素,但我是WPF的新手,我想知道我当前的工作实现是否可以改进.
我有一个仅由通知托盘图标组成的应用程序,我想从后台线程更新该图标.
这是我的Program.cs入口点:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (IconHandler notify = new IconHandler())
{
notify.Display();
Application.Run();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的IconHandler.cs通知图标处理程序类:
class IconHandler : IDisposable
{
NotifyIcon ni;
public IconHandler()
{
ni = new NotifyIcon();
}
public void Display()
{
ni.MouseClick += new MouseEventHandler(ni_MouseClick);
ni.Icon = Resources.icon1;
ni.Visible = true;
new Thread(new ThreadStart(UpdateIcon)).Start();
}
public void UpdateIcon()
{
while (true)
{
// reference ni directly, it updates fine
}
}
public void Dispose()
{
ni.Dispose();
}
void ni_MouseClick(object sender, MouseEventArgs e)
{
// something useful
}
}
Run Code Online (Sandbox Code Playgroud)
这有什么明显不正确的吗?这对我来说似乎有点可疑 - 这只是我的第一次尝试.它似乎适合我想做的事情,有没有人有任何更好的实施建议?我会在这个设置中遇到生命周期问题吗?
while(true)代码中的循环将导致大量 CPU/资源使用。也许将例如添加Thread.Sleep(1000)到循环中以允许更新之间的中断。
后台线程的最佳用法是在后台线程上执行长时间运行的工作(例如与服务器/数据库的通信),并且一旦线程完成,让 UI 线程更新 UI。
使用后台工作者:
var worker = new BackgroundWorker();
worker.DoWork += (sender, args) =>
{
// long running work
};
worker.RunWorkerCompleted += (sender, args) =>
{
// Update UI
};
worker.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)
异步/等待模式:
public async void DoWork()
{
// Do long running task
var data = await Task.Run(() => new object());
// Update UI here
}
Run Code Online (Sandbox Code Playgroud)
任务工厂:
Task.Factory.StartNew(() => new Object()).ContinueWith(task => MessageBox.Show(task.Result.ToString()), TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
如果 UI 需要不断循环更新,可以使用计时器定期重新启动该进程。这将使您的 CPU 免受冲击。
| 归档时间: |
|
| 查看次数: |
765 次 |
| 最近记录: |