当我的方法在后台 WPF 中执行某些操作时如何打开 window 或其他内容
How to open window or whatever while my method is doing something in background WPF
据我们所知,
程序正在逐行执行,现在我面临问题,我有一个方法需要几秒钟才能执行,
我以为我可以通过线程解决它但是我稍后会说,现在我想做的是:
当该方法开始执行时,我如何打开带有 "Still executing..." 等消息的 window 以及当方法完成时 window 可以关闭自己,
我需要它,因为我想避免 UI 冻结,因为那个长方法不在另一个 task/thread.
中
这是它的样子:
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
ExecuteLongMethod();
//When this is done close this method
}
谢谢大家,
干杯
一个示例,其中顶部 window/control 显示进度信息,主要 window 被禁用:
if (e.Key == Key.Delete)
{
// create a window with a progress ring or progress bar
var window = new Window();
new Thread(() =>
{
// execute long method
ExecuteLongMethod();
// close the progress window - release control
// ensure it is done on the UI thread
System.Windows.Application.Current.Dispatcher.Invoke(() => window.Close());
}).Start();
// display progress window
window.ShowDialog();
}
另一种方法是暂时禁用或隐藏可能干扰后台线程的任何 UI 元素(按钮、选项卡)并且不阻塞主线程 window。
如果您的 ExecuteLongMethod()
出于某种原因必须在调度程序线程上执行,您可以创建一个新的 window 在单独的线程中启动并在long-运行 方法完成。详情请参考以下link
另一种选择是在后台线程上执行 long-运行 方法并在主线程上显示加载 window。
推荐的方法是使用任务并行库 (TPL) 并启动任务:https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
if (e.Key == Key.Delete)
{
Window window = new Window();
window.Show();
Task.Factory.StartNew(() => ExecuteLongMethod())
.ContinueWith(task =>
{
window.Close();
},System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
使用等待模式
public void YourMethod()
{
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
FireAndForget();
//When this is done close this method
}
}
public async void FireAndForget()
{
await Task.Run(() => { ExecuteLongMethod(); });
}
即发即弃是一种反模式,但有时您会遇到无法永远等待的问题 - 就像 Commands
.
如果您想等待结果或直到结果完成,请像这样
public async void YourMethodAsync()
{
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
await CorrectWayAsync();
//When this is done close this method
}
}
public async Task CorrectWayAsync()
{
await Task.Run(() => { ExecuteLongMethod(); });
}
据我们所知, 程序正在逐行执行,现在我面临问题,我有一个方法需要几秒钟才能执行, 我以为我可以通过线程解决它但是我稍后会说,现在我想做的是:
当该方法开始执行时,我如何打开带有 "Still executing..." 等消息的 window 以及当方法完成时 window 可以关闭自己, 我需要它,因为我想避免 UI 冻结,因为那个长方法不在另一个 task/thread.
中这是它的样子:
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
ExecuteLongMethod();
//When this is done close this method
}
谢谢大家, 干杯
一个示例,其中顶部 window/control 显示进度信息,主要 window 被禁用:
if (e.Key == Key.Delete)
{
// create a window with a progress ring or progress bar
var window = new Window();
new Thread(() =>
{
// execute long method
ExecuteLongMethod();
// close the progress window - release control
// ensure it is done on the UI thread
System.Windows.Application.Current.Dispatcher.Invoke(() => window.Close());
}).Start();
// display progress window
window.ShowDialog();
}
另一种方法是暂时禁用或隐藏可能干扰后台线程的任何 UI 元素(按钮、选项卡)并且不阻塞主线程 window。
如果您的 ExecuteLongMethod()
出于某种原因必须在调度程序线程上执行,您可以创建一个新的 window 在单独的线程中启动并在long-运行 方法完成。详情请参考以下link
另一种选择是在后台线程上执行 long-运行 方法并在主线程上显示加载 window。
推荐的方法是使用任务并行库 (TPL) 并启动任务:https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
if (e.Key == Key.Delete)
{
Window window = new Window();
window.Show();
Task.Factory.StartNew(() => ExecuteLongMethod())
.ContinueWith(task =>
{
window.Close();
},System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
使用等待模式
public void YourMethod()
{
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
FireAndForget();
//When this is done close this method
}
}
public async void FireAndForget()
{
await Task.Run(() => { ExecuteLongMethod(); });
}
即发即弃是一种反模式,但有时您会遇到无法永远等待的问题 - 就像 Commands
.
如果您想等待结果或直到结果完成,请像这样
public async void YourMethodAsync()
{
if (e.Key == Key.Delete)
{
//Could I show window here like like "Loading please wait.."
await CorrectWayAsync();
//When this is done close this method
}
}
public async Task CorrectWayAsync()
{
await Task.Run(() => { ExecuteLongMethod(); });
}