在静态情况下使用异步更新UI不工作

问题描述:

我使用下面的代码在静态情况下使用异步更新UI不工作

public static class Program 
{ 
    [STAThread] 
    public static void Main(string[] args) 
    { 
     CancellationTokenSource tokenSource = new CancellationTokenSource(); 

     Task timerTask = Program.RunPeriodically(() => { Program.SendNotification($"foo", BalloonIcon.Info); }, TimeSpan.FromSeconds(10), tokenSource.Token); 
     timerTask.Wait(tokenSource.Token); 
    } 

    private static void SendNotification(string message, BalloonIcon balloonIcon) 
    { 
     new TaskbarIcon().ShowBalloonTip("Title", message, balloonIcon); 
    } 

    private static async Task RunPeriodically(Action action, TimeSpan interval, CancellationToken token) 
    { 
     while (true) 
     { 
      action(); 
      await Task.Delay(interval, token); 
     } 
    } 
} 

,我想要做的就是运行的方法SendNotification每10秒什么。为了达到这个目的,我把这个方法称为RunPeriodically

然而,呼叫SendNotifcation抛出InvalidOperationException,说:

调用线程必须为STA,因为许多UI组件都需要这个。

我也试过some suggestions使用Dispatcher这样

private static void SendNotification(string message, BalloonIcon balloonIcon) 
{ 
    Dispatcher.CurrentDispatcher.Invoke(() => 
    { 
     new TaskbarIcon().ShowBalloonTip("Title", message, balloonIcon); 
    }); 
} 

但它并没有做出改变。

我唯一的猜测是,该代码不起作用,因为它不是从一个Window实例调用,而是在没有this.Dispatcher一类的静态背景下,但我不知道如何使它在这方面的工作案件和我感谢任何帮助。

+1

如果您有更新的用户界面,您*不需要*控制台应用程序。尽管不明显,Windows窗体和WPF应用程序都是从Main函数开始的。这不会让他们*控制台*应用程序 –

+0

@PanagiotisKanavos是的,你是对的。谢谢。我将编辑问题标题以澄清这种误解。 –

+0

至于你的具体问题,只是*不*从另一个线程更新UI。使用async/await * await *在后台运行的任何内容,并在调用await后更新UI。 'await'不会让任何东西在后台运行。它*等待后台任务/作业完成,然后返回到UI线程。当你已经在UI线程 –

这个稍作修改的例子对我来说工作得很好。

希望它有帮助!

public static class Program 
{ 
    private static NotifyIcon notifyIcon; 

    [STAThread] 
    public static void Main(string[] args) 
    { 
     CancellationTokenSource tokenSource = new CancellationTokenSource(); 

     notifyIcon = new NotifyIcon(); 
     notifyIcon.Icon = SystemIcons.Information; 
     notifyIcon.BalloonTipTitle = "Title"; 
     notifyIcon.Visible = true; 

     Task timerTask = Program.RunPeriodically(() => { Program.SendNotification(DateTime.Now.ToString(), ToolTipIcon.Info); }, TimeSpan.FromSeconds(10), tokenSource.Token); 
     timerTask.Wait(tokenSource.Token); 
    } 

    private static void SendNotification(string message, ToolTipIcon balloonIcon) 
    { 
     notifyIcon.BalloonTipIcon = balloonIcon; 
     notifyIcon.BalloonTipText = message; 
     notifyIcon.ShowBalloonTip(500); 
    } 

    private static async Task RunPeriodically(Action action, TimeSpan interval, CancellationToken token) 
    { 
     while (true) 
     { 
      action(); 
      await Task.Delay(interval, token); 
     } 
    } 
} 
+0

为我解决了这个问题。像魅力一样工作,谢谢! –