我已經在BackgroundWorker中使用過這種類型的東西,但我想使用.NET 4.5的新異步/等待方法。我可能會吠叫錯誤的樹。請指教。使用WinForms進行異步/等待ProgressBar
目標:創建一個組件,它將執行一些長時間運行的工作,並在進行工作時顯示帶有進度條的模態窗體。該組件將獲取窗口的句柄,以在執行長時間運行的工作時阻止交互。
狀態:請參閱下面的代碼。我以爲自己做得很好,直到我嘗試與窗口交互。如果我把事情放在一邊(即不要碰!),一切都會「完美地」運行,但是如果我點擊任一窗口,程序就會在長時間運行結束後掛起。實際的交互(拖動)被忽略,就像UI線程被阻塞一樣。
問題:我的代碼可以很容易地修復嗎?如果是這樣,怎麼樣?或者,我應該使用其他方法(例如BackgroundWorker)嗎?
代碼(Form1上是一個標準的形式與進度和公共方法,的UpdateProgress中,設定進度的值):
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting..");
var mgr = new Manager();
mgr.GoAsync();
Console.WriteLine("..Ended");
Console.ReadKey();
}
}
class Manager
{
private static Form1 _progressForm;
public async void GoAsync()
{
var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle);
_progressForm = new Form1();
_progressForm.Show(owner);
await Go();
_progressForm.Hide();
}
private async Task<bool> Go()
{
var job = new LongJob();
job.OnProgress += job_OnProgress;
job.Spin();
return true;
}
void job_OnProgress(int percent)
{
_progressForm.UpdateProgress(percent);
}
}
class LongJob
{
public event Progressed OnProgress;
public delegate void Progressed(int percent);
public void Spin()
{
for (var i = 1; i <= 100; i++)
{
Thread.Sleep(25);
if (OnProgress != null)
{
OnProgress(i);
}
}
}
}
class Win32Window : IWin32Window
{
private readonly IntPtr _hwnd;
public Win32Window(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get
{
return _hwnd;
}
}
}
}
如果Go(progress)拋出一個異常,那麼_progressForm.Close()永遠不會被調用 - >模式對話框將永遠掛起 – Hiep
並且最好將「_progressForm.Activated」更改爲「_progressForm.Shown」,因爲_progressForm可能被激活多次在他一生中的時間.. - >去(進展)將被稱爲多次.. – Hiep
https://gist.github.com/duongphuhiep/f83f98593d93045e717f – Hiep