如何在进行涉及访问UI控件的耗时工作时不阻塞UI
本文关键字:UI 工作 控件 访问 | 更新日期: 2023-09-27 18:27:24
我有一个方法很耗时,因此我一直在尝试实现BackgroundWorker,但它不允许访问我已经阅读并尝试过的UI控件(对其进行黑客攻击),但没有成功。
我的方法是:创建一个新的BitmapImage
,将源设置为本地或流式(参数),将其写入用于ConvertToGrayscale
的新WriteableBitmap
,然后将BW Copy保存到文件夹中的IsolatedStorage
。
所以这一切发生得很快。但是,只有当我说少于25个源图像时。如果我有大约100多个图像,这需要相当长的时间,比如20秒或更长时间,因此,我想在同一个PhoneApplicationPage
中显示ProgressBar,但我一直在努力解决如何在该方法工作时不阻塞UI并显示ProgressBar。
这是我的代码:
void GetImages()
{
if (!myIsolatedStorage.DirectoryExists("ImagesBW") && !_appsettings.Contains("_update"))
{
myIsolatedStorage.CreateDirectory("ImagesBW ");
for (int i = 0; i < coll.Desserts.Count; i++)
{
BitmapImage bmp = new BitmapImage();
bmp.CreateOptions = BitmapCreateOptions.None;
if (coll.Desserts[i].HasAssociatedImage)
{
bmp.SetSource(coll.Desserts[i].GetImage());
WriteableBitmap wb = new WriteableBitmap(bmp);
ConvertToGrayscale(wb);
BitmapImage bit = ConvertWBtoBI(wb);
SaveBWCopy(bi, i.ToString());
}
else
{
bmp.UriSource = new Uri("/Assets/Images/MissingArt.png", UriKind.Relative);
WriteableBitmap wb = new WriteableBitmap(bmp);
ConvertToGrayscale(wb);
BitmapImage bit = ConvertWBtoBI(wb);
SaveBWCopy(bi, i.ToString());
}
}
_appsettings["_firstLaunch"] = "false";
_appsettings.Save();
}
else if (myIsolatedStorage.DirectoryExists("ImagesBW ") && _appsettings.Contains("_update"))
{
string[] files = myIsolatedStorage.GetFileNames("ImagesBW/*");
for (int s = 0; s < files.Length; s++)
{
myIsolatedStorage.DeleteFile("ImagesBW/" + s + ".jpg");
}
myIsolatedStorage.DeleteDirectory("ImagesBW");
myIsolatedStorage.CreateDirectory("ImagesBW");
for (int i = 0; i < coll.Desserts.Count; i++)
{
BitmapImage bmp = new BitmapImage();
bmp.CreateOptions = BitmapCreateOptions.None;
if (coll.Desserts[i].HasAssociatedImage)
{
bmp.SetSource(coll.Desserts[i].GetImage());
WriteableBitmap wb = new WriteableBitmap(bmp);
ConvertToGrayscale(wb);
BitmapImage bit = ConvertWBtoBI(wb);
SaveBWCopy(bi, i.ToString());
}
else
{
bmp.UriSource = new Uri("/Assets/Images/MissingArt.png", UriKind.Relative);
WriteableBitmap wb = new WriteableBitmap(bmp);
ConvertToGrayscale(wb);
BitmapImage bit = ConvertWBtoBI(wb);
SaveBWCopy(bi, i.ToString());
}
}
_appsettings.Remove("_update");
_appsettings.Save();
}
btnStart.IsEnabled = true;
}
Backgroundworker是您的最佳选择。web上有大量的资源来实现它。但其背后的想法是Backgroundworker在独立于UI的线程中运行。您可以通过两种方法访问主线程UI,一种是委托,另一种是通过Backgroundworker的ProgressChanged方法,该方法可以访问UI线程。
假设你有这个。
public MainWindow()
{
InitializeComponent();
//if you want to disable you button you can do it here
BackgroundWorker _bw = new BackgroundWorker();
_bw.DoWork += new DoWorkEventHandler(_bw_DoWork);
_bw.WorkerReportsProgress = true;
_bw.ProgressChanged += new ProgressChangedEventHandler(_bw_ProgressChanged);
_bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_bw_RunWorkerCompleted);
_bw.RunWorkerAsync();
//or here
//Display progress bar here too
}
void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this can give you access to the UI after work is completed
// to check that everything is ok or hide progress bar
}
void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//this will give you access to the UI in the middle of you work like update progress bar
}
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
//actual work here including GetImages
//work work work
GetImages();
}
在SaveBWCopy之后的getimages方法中,您可以添加此来更新进度条
_bw.ReportProgress(int progress )
//progress is the percentage you want to send to progress bar to display that is going to be in the e eventargument you passed.