Düzenleme Ben zorlama uygun yolu bu gibi uyumsuz işçiyi çağırmak bir Task.Run ile karşı bekliyor herhalde ilerleme/iptali ile uzun süren API yöntemleri için bekliyor:Async/
await Task.Run(() => builder.Build(dlg.FileName, cts.Token, new Progress(ReportProgress)));
http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293335.aspx'dan biraz ışık aldım.
bu kolay olmalı, ancak uyumsuzluk/beklemede yeniyim, bu yüzden benimle kalmayın. Uzun süredir devam eden operasyonlarla bir API açığa çıkaran bir sınıf kütüphanesi yapıyorum.
public void DoSomething(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = (BackgroundWorker)sender;
// e.Argument is any object as passed by consumer via RunWorkerAsync...
do
{
// ... do something ...
// abort if requested
if (bw.CancellationPending)
{
e.Cancel = true;
break;
} //eif
// notify progress
bw.ReportProgress(nPercent);
}
}
ve benzeri istemci kodu oldu: İsterdim Şimdi
BackgroundWorker worker = new BackgroundWorker
{ WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
worker.DoWork += new DoWorkEventHandler(_myWorkerClass.DoSomething);
worker.ProgressChanged += WorkerProgressChanged;
worker.RunWorkerCompleted += WorkerCompleted;
worker.RunWorkerAsync(someparam);
Eskiden ilerleme raporlama ve iptal gibi bu basitleştirilmiş kod parçasını başa BackgroundWorker kullanılan Yeni zaman uyumsuz kalıbı. Dolayısıyla, öncelikle burada API'mda uzun süren basit bir yöntem yazacağım; Burada sadece bazı işleme ile bir dosya biçimi dönüştürme sahip olacakları sadece gerçek dünya sürecini taklit, satır bir dosya satır okuyorum: Bu örnek uğruna
public async Task DoSomething(string sInputFileName, CancellationToken? cancel, IProgress progress)
{
using (StreamReader reader = new StreamReader(sInputFileName))
{
int nLine = 0;
int nTotalLines = CountLines(sInputFileName);
while ((sLine = reader.ReadLine()) != null)
{
nLine++;
// do something here...
if ((cancel.HasValue) && (cancel.Value.IsCancellationRequested)) break;
if (progress != null) progress.Report(nLine * 100/nTotalLines);
}
return nLine;
}
}
, bu demek bir DummyWorker sınıfının bir yöntemidir. bu URL başvurabilmeniz için
private void ReportProgress(int n)
{
Dispatcher.BeginInvoke((Action)(() => { _progress.Value = n; }));
}
private async void OnDoSomethingClick(object sender, RoutedEventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog { Filter = "Text Files (*.txt)|*.txt" };
if (dlg.ShowDialog() == false) return;
// show the job progress UI...
CancellationTokenSource cts = new CancellationTokenSource();
DummyWorker worker = new DummyWorker();
await builder.Build(dlg.FileName, cts.Token, new Progress(ReportProgress));
// hide the progress UI...
}
IProgress arayüzü için uygulama, http://blog.stephencleary.com/2010/06/reporting-progress-from-tasks.html geliyor: Şimdi, burada müvekkilim kodu (WPF test uygulaması) 'dir. Her neyse, bu kullanım testinde UI etkili bir şekilde engellenir ve hiçbir ilerleme göremiyorum. Öyleyse, böyle bir senaryonun, tüketici koduyla ilgili olarak tam resmi ne olurdu?
Evet, 'Task.Run()' bunu yapmanın yoludur. Ya da eylem gerçekten uzun ise, 'LongRunning' seçeneği ile Task.Factory.StartNew()'. – svick