[英]WPF C#: Using Tasks
我已經閱讀了幾個不同的帖子,我真的無法理解這個!
我有以下類,當用戶選擇了一個驅動器並設置DriveInfo sel
,運行DoUpload
方法,並將DoUpload
圖像轉換為字節格式。
現在這需要幾秒鍾在我的機器上,但是更多的圖像和更慢的機器可能需要更長的時間,所以我想在另一個線程上執行此操作,但每次轉換圖像時,我想通知UI,在我的情況下我想要更新以下屬性:縮略圖,文件名,步驟,UploadProgress。
同樣,我想在每次轉換圖像時更新上面的屬性,如何使用Task API執行此操作?
這是班級:
public class UploadInitiation : Common.NotifyUIBase
{
#region Public Properties
/// <summary>
/// File lists
/// </summary>
/// public ObservableCollection<BitmapImage> Thumbnail_Bitmaps { get; set; } = new ObservableCollection<BitmapImage>();
public ObservableCollection<ByteImage> Thumbnails { get; set; } = new ObservableCollection<ByteImage>();
public ObservableCollection<NFile> Filenames { get; set; } = new ObservableCollection<NFile>();
/// <summary>
/// Updates
/// </summary>
public ObservableCollection<UploadStep> Steps { get; set; } = new ObservableCollection<UploadStep>();
public int UploadProgress { get; set; } = 45;
public string UploadTask { get; set; } = "Idle...";
public bool UploadEnabled { get; set; } = false;
private bool _uploadBegin;
public bool UploadBegin
{
set { _uploadBegin = value; RaisePropertyChanged(); }
get { return _uploadBegin; }
}
#endregion END Public Properties
public UploadInitiation()
{
// Populate steps required, ensure upload returns UI updates
Steps.Add(new UploadStep { Message = "First task...", Complete = true, Error = null });
Steps.Add(new UploadStep { Message = "Error testing task...", Complete = false, Error = "testing error" });
Steps.Add(new UploadStep { Message = "Seperate upload to new thread...", Complete = false, Error = null });
Steps.Add(new UploadStep { Message = "Generate new file names...", Complete = false, Error = null });
Steps.Add(new UploadStep { Message = "Render Thumbnails, add to database...", Complete = false, Error = null });
Steps.Add(new UploadStep { Message = "Move images ready for print...", Complete = false, Error = null });
}
/// <summary>
/// This Method will perform the upload on a seperate thread.
/// Report progress back by updating public properties of this class.
/// </summary>
/// <param name="sel"></param>
public void DoUpload(DriveInfo sel)
{
// Check that there is a device selected
if (sel != null)
{
// Generate List of images to upload
var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".jpeg") || s.EndsWith(".jpg") || s.EndsWith(".png"));
if (files.Count() > 0)
{
// Manage each image
foreach (string item in files)
{
// Generate thumbnail byte array
Thumbnails.Add(new ByteImage { Image = GenerateThumbnailBinary(item) });
}
foreach (string item in files)
{
// Generate new name
Filenames.Add(
new NFile
{
OldName = Path.GetFileNameWithoutExtension(item),
NewName = Common.Security.KeyGenerator.GetUniqueKey(32)
});
}
}
}
}
public byte[] GenerateThumbnailBinary(string loc)
{
BitmapImage image = new BitmapImage(new Uri(loc));
Stream stream = File.OpenRead(loc);
byte[] binaryImage = new byte[stream.Length];
stream.Read(binaryImage,0,(int)stream.Length);
return binaryImage;
}
有一個內置的類Progress ,可以向UI線程報告進度。
public async void StartProcessingButton_Click(object sender, EventArgs e)
{
// The Progress<T> constructor captures our UI context,
// so the lambda will be run on the UI thread.
var progress = new Progress<int>(percent =>
{
textBox1.Text = percent + "%";
});
// DoProcessing is run on the thread pool.
await Task.Run(() => DoProcessing(progress));
textBox1.Text = "Done!";
}
public void DoProcessing(IProgress<int> progress)
{
for (int i = 0; i != 100; ++i)
{
Thread.Sleep(100); // CPU-bound work
if (progress != null)
progress.Report(i);
}
}
了解更多關於進步記者在這里與異步/等待。
更新 -
以下是您在代碼中執行此操作以報告進度的方法。
使用progresschanged處理程序定義進度對象。 下面是一個帶有匿名處理程序的示例。
IProgress<UploadStep> progress = new Progress<UploadStep>(step =>
{
// sample consumption of progress changed event.
if (step.Complete)
{
// Do what ever you want at the end.
}
else
{
statusTxtBox.Text = step.Message;
}
});
使用此Progress對象調用DoUpload
DoUpload(driveInfo, progress);
現在,在您的DoUpload方法中進行更改:
public void DoUpload(DriveInfo sel, IProgress<UploadStep> progress)
{
// Check that there is a device selected
if (sel != null)
{
progress.Report(new UploadStep { Message = "First Task..." });
// Generate List of images to upload
var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".jpeg") || s.EndsWith(".jpg") || s.EndsWith(".png"));
if (files.Count() > 0)
{
// Manage each image
foreach (string item in files)
{
// Generate thumbnail byte array
Thumbnails.Add(new ByteImage { Image = GenerateThumbnailBinary(item) });
}
progress.Report(new UploadStep { Message = "Generated Thumnails..." });
foreach (string item in files)
{
// Generate new name
Filenames.Add(
new NFile
{
OldName = Path.GetFileNameWithoutExtension(item),
NewName = Common.Security.KeyGenerator.GetUniqueKey(32)
});
}
progress.Report(new UploadStep { Message = "Uplaoding to database..." });
}
}
}
我將創建一個單獨的Thread
並將列表和Dispatcher傳遞給它。 每次項目准備就緒時,您應該Invoke
Dispatcher
並設置結果。
var list<UploadStep> items = new List<UploadStep>();
// queue workitems
var currentDispatcher = Dispatcher.CurrentDispatcher;
var thread = new Thread(() =>
{
foreach(var item in items)
{
// do you thing with downloading..
currentDispatcher.Invoke(() =>
{
// Add to observable class or other gui items..
});
}
});
thread.Start();
如果您想使用任務庫進行操作,則應等待每個項目。
var list<UploadStep> items = new List<UploadStep>();
foreach(var step in items)
{
var myResults = await DoYourDownload(step);
// Change some gui stuff.
}
所有這些項目將連續處理。
這是一篇關於如何並行處理它們的文章: 在foreach循環中啟動任務使用最后一項的值
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.