如何弹出依赖后台任务逻辑的消息?
本文关键字:消息 何弹出 依赖 后台任务 | 更新日期: 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; });
}