Ho avuto questo tipo di cose che funzionano in passato con un BackgroundWorker, ma voglio usare il nuovo approccio async/await di .NET 4.5. Potrei essere abbaiare sull'albero sbagliato. Si prega di avvisare.Async/Attesa con WinForms ProgressBar
Obiettivo: creare un componente che eseguirà un lavoro di lunga durata e mostrerà un modulo modale con una barra di avanzamento mentre esegue il lavoro. Il componente otterrà l'handle di una finestra per bloccare l'interazione mentre sta eseguendo il lavoro di lunga durata.
Stato: Vedere il codice di seguito. Pensavo di stare bene fino a quando ho provato a interagire con Windows. Se lascio le cose da solo (vale a dire non toccare!), Tutto gira "perfettamente", ma se faccio così tanto clic su una finestra il programma si blocca dopo il lavoro a lungo termine. Le interazioni reali (trascinamento) vengono ignorate come se il thread dell'interfaccia utente fosse bloccato.
Domande: il mio codice può essere risolto abbastanza facilmente? Se é cosi, come? Oppure, dovrei utilizzare un approccio diverso (ad esempio, BackgroundWorker)?
Codice (Form1 è una forma standard con un ProgressBar e un metodo pubblico, UpdateProgress, che imposta il valore del ProgressBar):
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;
}
}
}
}
se Go (avanzamento) genera un'eccezione, quindi _progressForm.Close() non verrà mai chiamato -> la finestra di dialogo modale verrà bloccata per sempre – Hiep
Ed è meglio cambiare "_progressForm.Activated" in "_progressForm .Shown" perché _progressForm potrebbe essere attivato più volte durante la sua vita .. -> Vai (progresso) sarà chiamato più volte .. – Hiep
https://gist.github.com/duongphuhiep/f83f98593d93045e717f – Hiep