使用 C# 的 WPF 中的多线程(使用后台工作程序)
我编写了代码来保存应用程序生成的图像。图像大小约为 32-35 MB。将图像保存到 BMB 文件时,需要很长时间,大约 3-5 秒。为此,我使用了后台工作程序,但在运行后台工作程序时,它显示一个错误,例如...“无法访问该对象,因为它是在不同线程上创建的”。
以下是代码:
private void btnSaveDesign_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
sfd.Title = "Save design as...";
sfd.Filter = "BMP|*.bmp";
if (sfd.ShowDialog() == true)
{
ww = new winWait();
ww.Show();
System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
fName = sfd.FileName;
cache = new CachedBitmap((BitmapSource)imgOut.Source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
bw.RunWorkerAsync();
}
}
void bw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
ww.Close();
}
void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(cache)); //here... it says cant access...
using (FileStream file = File.OpenWrite(fName))
{
encoder.Save(file);
}
}
我已将“缓存”声明为全局对象。 (当我使用 VB.NET 在 Windows 窗体中进行编程时,类似的技巧起作用了。)
ww
是我希望在执行过程时显示的等待窗口。
如何做到这一点? WPF中还有其他简单的多线程方法吗?
I have written code to save an image which is generated by the application. The size of the image is around 32-35 MB. While saving the image to a BMB file, it is taking a long time, around 3-5 secs. For this purpose, I have used a background worker but when running the background worker, it shows an error like..."can't access the object as it is created on different thread".
Following is the code:
private void btnSaveDesign_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
sfd.Title = "Save design as...";
sfd.Filter = "BMP|*.bmp";
if (sfd.ShowDialog() == true)
{
ww = new winWait();
ww.Show();
System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
fName = sfd.FileName;
cache = new CachedBitmap((BitmapSource)imgOut.Source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
bw.RunWorkerAsync();
}
}
void bw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
ww.Close();
}
void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(cache)); //here... it says cant access...
using (FileStream file = File.OpenWrite(fName))
{
encoder.Save(file);
}
}
I have declared "cache" as a global object. (A similar trick worked when I was programming in Windows Forms with VB.NET.)
ww
is the wait window that I want to be displayed while the precess is being executed.
How to do this? Is there any other simple method for multi threading in WPF?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
创建 WPF 对象时,它们被分配给 Dispatcher 对象。这不允许除创建线程之外的任何线程访问该对象。可以通过调用 freeze 方法冻结对象来避免这种情况。您需要对位图源对象调用 Freeze。一旦你冻结了你的对象,它就变得不可编辑
When WPF objects are created they are assigned to a Dispatcher object. This disallows any threads other than the creating thread to access the object. This can be circumvented by freezing the object by calling the freeze method. You would need to call Freeze on your bitmapsource object. Once you have frozen your object it becomes uneditable
出现您的问题是因为您正在访问不是由后台工作线程创建的对象。通常,如果您访问在主线程中创建并从不同线程访问的 UI 控件,就会发生这种情况。
使用下面的代码。
Your problem comes about because you are accessing an object which is not created by the background worker thread. Normally this would happen if you access a UI control which is created in the main thread and accessed from different thread.
Use the code below.
我认为你必须将缓存作为参数传递给新线程:
并从 DoWork 方法获取它:
I think you have to pass cache as a parameter to the new thread:
and get it from the DoWork method: