如何弹出依赖后台任务逻辑的消息?

本文关键字:消息 何弹出 依赖 后台任务 | 更新日期: 2023-09-27 18:15:58

现在我有如下内容:

private void DoSomethingAsync() {
    ProgressBarVisibility = Visibility.Visible;
    Task.Factory.StartNew(() => { PerformCDDetection(); }).ContinueWith(t => { ProgressBarVisibility = Visibility.Collapsed; });
}

 public ICommand ImportFilePathCommand
{
    get
    {
        return new RelayCommand(() => { DoSomethingAsync(); });
    }
}
  private void PerformCDDetection()
{
    //Gets all the drives 
    DriveInfo[] allDrives = DriveInfo.GetDrives();
    //checks if any CD-Rom exists in the drives
    var cdRomExists = allDrives.Any(x => x.DriveType == DriveType.CDRom);
    // Get all the cd roms
    var cdRoms = allDrives.Where(x => x.DriveType == DriveType.CDRom && allDrives.Any(y => y.IsReady));
    if (cdRomExists.Equals(true))
    {
        // Loop through the cd roms collection
        foreach(var cdRom in cdRoms)
        {
            Console.WriteLine("Drive {0}", cdRom.Name);
            Console.WriteLine("  File type: {0}", cdRom.DriveType);
            if (cdRom.IsReady == true)
            {
                if (cdRom.DriveType == DriveType.CDRom)
                {
                    DirectoryInfo di = new DirectoryInfo(cdRom.RootDirectory.Name);
                    var file = di.GetFiles("*.xml", SearchOption.AllDirectories).FirstOrDefault();
                    if (file == null)
                    {
                        Console.WriteLine("failed to find file"); 
                    }
                    else
                    {
                        foreach (FileInfo info in di.GetFiles("*.xml", SearchOption.AllDirectories))
                        {
                            Debug.Print(info.FullName);
                            break;      // only looking for the first one
                        }
                        break;
                    }
                }
            }
            else if (cdRom.IsReady == false)
            {
                Console.WriteLine("Cd-ROM is not ready");
                break;
            }
        }
    }
    else
    {
        Console.WriteLine("CD ROM is not detected");
    }
} 

控制台。WriteLine语句应该是弹出的对话框/消息框,提醒用户列出的条件。

我删除了消息,并用Console代替了它。WriteLine语句,因为我不能在后台任务上运行messagebox.show()(它应该是UI线程的一部分,而不是后台)。

我想知道由于消息是基于在后台执行的逻辑显示的,我如何显示消息框?

在下面的例子中,我怎么做才能在UI线程和后台线程之间来回切换?

编辑:这是我想在UI线程上运行的一段代码:

  errorWindow.Message = LanguageResources.Resource.File_Not_Found;
  dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
  break;

如果我这样做:

Dispatcher.BeginInvoke(() =>
{
    errorWindow.Message = LanguageResources.Resource.File_Not_Found;
    dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
    break;
}
);

我得到这些错误信息:

Control cannot leave the body of an anonymous method or lambda expression (for break;)
Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type    

我使用break来跳出循环,我应该只是移动我的逻辑来避免使用break还是有一种方法,我仍然可以使用break?

如何弹出依赖后台任务逻辑的消息?

你可以创建一个可重用的MessageService,可以从你的应用程序的任何部分访问或调用。

像这样:

注意:这段代码假设MessageService实例是在一个UI线程上创建的。通常情况下,如果你注入这个实例到你的容器在BootStrapper。否则,即使您从任何.xaml.cs代码中实例化,也可以工作。

        /// <summary>
        /// Could be injected to your UnityContainer as singleton and then accessed by using Container.Resolve
        /// </summary>
    public interface IMessageService
    {
        void ShowDialog(string message, MessageBoxButton messageBoxButton);
    }
    public class MessageService : IMessageService
    {
        private readonly Dispatcher _dispatcher;
        public MessageService()
        {
          if(Application.Current!=null){
             _dispatcher = Application.Current.Dispatcher;
          }
          else{
            _dispatcher = Dispatcher.CurrentDispatcher;
          }
        }
        public void ShowDialog(string message, MessageBoxButton messageBoxButton)
        {
            if (_dispatcher.CheckAccess())
            {
                Show(message, messageBoxButton);
            }
            else
            {
                _dispatcher.Invoke(new Action(() => Show(message, messageBoxButton)));
            }
        }
        private static void Show(string message, MessageBoxButton messageBoxButton)
        {
            MessageBox.Show(Application.Current.MainWindow, message, "TITLE", messageBoxButton);
        }
    }

编辑:如果不使用任何统一容器,你可以简单地从你的代码中实例化MessageService。就像在"DoSomethingAsync"里面一样

您应该查看Dispatcher。调用和分派器。BeginInvoke方法。

MSDN链接:http://msdn.microsoft.com/en-us/library/System.Windows.Threading.Dispatcher_methods%28v=vs.110%29.aspx

你可以这样做:

Dispatcher.BeginInvoke((Action)(() => MessageBox.Show("some message to display")));

控件不能离开匿名方法或lambda的主体表达式(for break;)

分隔符需要在Dispatcher调用之外。你可以这样做:

Dispatcher.BeginInvoke(...);
break;

只是为了让别人看到:

正如在聊天中所讨论的,您需要从UI线程中获取调度程序,然后将其传递给您的任务。

的例子:

private void DoSomethingAsync() {
    /* here we are on the UI thread */
    Dispatcher dispatcher = (Application.Current!=null) ?
         Application.Current.Dispatcher :
         Dispatcher.CurrentDispatcher;
    ProgressBarVisibility = Visibility.Visible;
    Task.Factory.StartNew(() => { 
             /* here we are on the background thread */ 
             PerformCDDetection(dispatcher); 
         }).ContinueWith(t => { ProgressBarVisibility = Visibility.Collapsed; });
}

你需要对Manish的类做同样的事情:

private void DoSomethingAsync() {
    MessageService messageService = new MessageService();
    ProgressBarVisibility = Visibility.Visible;
    Task.Factory.StartNew(() => { PerformCDDetection(messageService); }).ContinueWith(t => { ProgressBarVisibility = Visibility.Collapsed; });
}