Wpf 在另一个线程中使用BitmapDecoder,然后在何处创建。(调用线程无法访问此对象,因为其他线程拥有它。)
因此,我有一个函数,可以从另一个线程的磁盘异步加载一个映像(将加载大映像,我不希望在加载时锁定UI线程) 加载是这样完成的Wpf 在另一个线程中使用BitmapDecoder,然后在何处创建。(调用线程无法访问此对象,因为其他线程拥有它。),wpf,multithreading,bitmap,Wpf,Multithreading,Bitmap,因此,我有一个函数,可以从另一个线程的磁盘异步加载一个映像(将加载大映像,我不希望在加载时锁定UI线程) 加载是这样完成的 public override void LoadFile() { using (var imageStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { De
public override void LoadFile()
{
using (var imageStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Decoder = new TiffBitmapDecoder(imageStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
InitializeFile();
}
}
然后我想在主线程上使用解码器
public List<ThumbnailModel> LoadPages()
{
var result = new List<ThumbnailModel>();
foreach (var frame in Decoder.Frames) <--// this line throws exception
{
result.Add(new ThumbnailModel
{
Name = _metadataLoader.GetPageName((BitmapMetadata)frame.Metadata),
Bitmap = new WriteableBitmap(frame)
});
}
return result;
}
在获得IImageFile后,我们调用MainThread(UIThread)
其中LoadPages是应用程序中断的位置。也在UIThread上调用
公共列表加载页()
{
var result=新列表()
我认为您可以简单地从线程返回解码器,以便能够访问它,但您的解码器是从DispatcherObject()继承的TiffBitmapDecoder 因此,您将无法从创建它的线程以外的其他线程访问它。msdn:“只有创建Dispatcher的线程可以直接访问DispatcherObject” 您可以改为在其线程中使用解码器并返回最终结果: 我无法基于您的样本进行构建,因为我缺少很多东西来测试它,但我构建了一个类似的项目来提供一个示例:
public partial class MainWindow : Window
{
public MainWindow()
{
}
public TiffBitmapDecoder LoadFile()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "tiff files (*.tif)|*.tif|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == true && !string.IsNullOrEmpty(openFileDialog.FileName))
{
//I didn't bother to check the file extension since it's just an exemple
using (var imageStream = openFileDialog.OpenFile())
{
return new TiffBitmapDecoder(imageStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
}
}
else
{
//User cancelled
return null;
}
}
public List<ThumbnailModel> LoadPages(TiffBitmapDecoder decoder)
{
//TiffBitmapDecoder" inherits from DispatcherObject/>
//https://docs.microsoft.com/en-gb/dotnet/api/system.windows.threading.dispatcherobject?view=netcore-3.1
var result = new List<ThumbnailModel>();
if (decoder != null)
{
try
{
foreach (var frame in decoder.Frames)
{
result.Add(new ThumbnailModel
{
//set the variables
});
}
}
catch(InvalidOperationException e)
{
MessageBox.Show(e.Message, "Error");
}
}
else
{
//Nothing to do
}
return result;
}
private async Task AsyncLoading()
{
this.thumbnailModels = await Task.Run<List<ThumbnailModel>>(() =>
{
var decoder = this.LoadFile();
return this.LoadPages(decoder);
});
}
private List<ThumbnailModel> thumbnailModels = null;
private async void AsyncLoadingButton_Click(object sender, RoutedEventArgs e)
{
await this.AsyncLoading();
}
}
public class ThumbnailModel
{
}
公共部分类主窗口:窗口
{
公共主窗口()
{
}
公共TiffBitmapDecoder加载文件()
{
OpenFileDialog OpenFileDialog=新建OpenFileDialog();
openFileDialog.InitialDirectory=“c:\\”;
openFileDialog.Filter=“tiff文件(*.tif)|*.tif |所有文件(*.*)|*.”;
openFileDialog.FilterIndex=2;
openFileDialog.RestoreDirectory=true;
if(openFileDialog.ShowDialog()==true&&!string.IsNullOrEmpty(openFileDialog.FileName))
{
//我没有检查文件扩展名,因为它只是一个示例
使用(var imageStream=openFileDialog.OpenFile())
{
返回新的TiffBitmapDecoder(imageStream、BitmapCreateOptions.PreservePixelFormat、BitmapCacheOption.OnLoad);
}
}
其他的
{
//用户取消
返回null;
}
}
公共列表加载页(TiffBitmapDecoder)
{
//TiffBitmapDecoder“继承自DispatcherObject/>
//https://docs.microsoft.com/en-gb/dotnet/api/system.windows.threading.dispatcherobject?view=netcore-3.1
var result=新列表();
if(解码器!=null)
{
尝试
{
foreach(解码器中的var帧。帧)
{
结果。添加(新的缩略图模型)
{
//设置变量
});
}
}
捕获(无效操作异常)
{
MessageBox.Show(例如,Message,“Error”);
}
}
其他的
{
//无事可做
}
返回结果;
}
专用异步任务异步加载()
{
this.thumbnailModels=等待任务。运行(()=>
{
var decoder=this.LoadFile();
返回此.LoadPages(解码器);
});
}
私有列表thumbnailModels=null;
私有异步void AsyncLoadingButton_单击(对象发送方,RoutedEventTarget e)
{
等待此消息。AsyncLoading();
}
}
公共类缩略图模型
{
}
MainWindow.xaml的内容以防万一:
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="NoReturnButton" Margin="10" HorizontalAlignment="Center" Content="Call AsyncLoadingNoReturn" Click="AsyncLoadingButton_Click" />
</StackPanel>
</Grid>
如果您进行“加载”"线程返回解码器,您应该能够在主线程中访问。在没有看到所有代码的情况下,我无法真正给出示例。@Ostas我将在一秒钟内更新代码。下周我将对其进行测试,并给出一个答案,如果它对我的情况有帮助,无论如何,非常感谢您的努力。这不会解决我的问题,因为我必须返回一个接口from加载文件(),但您的答案回答了我的问题。我无法在其他线程中使用解码器,因此我将其标记为答案。谢谢
foreach (var frame in Decoder.Frames)
{
result.Add(new ThumbnailModel
{
Name = _metadataLoader.GetPageName((BitmapMetadata)frame.Metadata),
Bitmap = new WriteableBitmap(frame)
});
}
return result;
}
public partial class MainWindow : Window
{
public MainWindow()
{
}
public TiffBitmapDecoder LoadFile()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "tiff files (*.tif)|*.tif|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == true && !string.IsNullOrEmpty(openFileDialog.FileName))
{
//I didn't bother to check the file extension since it's just an exemple
using (var imageStream = openFileDialog.OpenFile())
{
return new TiffBitmapDecoder(imageStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
}
}
else
{
//User cancelled
return null;
}
}
public List<ThumbnailModel> LoadPages(TiffBitmapDecoder decoder)
{
//TiffBitmapDecoder" inherits from DispatcherObject/>
//https://docs.microsoft.com/en-gb/dotnet/api/system.windows.threading.dispatcherobject?view=netcore-3.1
var result = new List<ThumbnailModel>();
if (decoder != null)
{
try
{
foreach (var frame in decoder.Frames)
{
result.Add(new ThumbnailModel
{
//set the variables
});
}
}
catch(InvalidOperationException e)
{
MessageBox.Show(e.Message, "Error");
}
}
else
{
//Nothing to do
}
return result;
}
private async Task AsyncLoading()
{
this.thumbnailModels = await Task.Run<List<ThumbnailModel>>(() =>
{
var decoder = this.LoadFile();
return this.LoadPages(decoder);
});
}
private List<ThumbnailModel> thumbnailModels = null;
private async void AsyncLoadingButton_Click(object sender, RoutedEventArgs e)
{
await this.AsyncLoading();
}
}
public class ThumbnailModel
{
}
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="NoReturnButton" Margin="10" HorizontalAlignment="Center" Content="Call AsyncLoadingNoReturn" Click="AsyncLoadingButton_Click" />
</StackPanel>
</Grid>