Tôi đang tạo một Cửa sổ trong một chủ đề khác được đánh dấu STA cửa sổ này có một vài điều khiển và hình ảnh.Xử lý ảnh trong WPF không phải là chủ đề an toàn?
tôi hơn đi và đóng cửa sổ này và mở một cửa sổ khác trong giao diện người dùng chính Chủ đề trong này tôi có một hộp thoại in và sử dụng đoạn mã sau để có được một FixedDocumentSequence
:
var tempFileName = System.IO.Path.GetTempFileName();
File.Delete(tempFileName);
using (var xpsDocument = new XpsDocument(tempFileName, FileAccess.ReadWrite, CompressionOption.NotCompressed))
{
var writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(this.DocumentPaginator);
}
using (var xpsDocument = new XpsDocument(tempFileName, FileAccess.Read, CompressionOption.NotCompressed))
{
var xpsDoc = xpsDocument.GetFixedDocumentSequence();
return xpsDoc;
}
Trên dòng:
writer.Write(this.DocumentPaginator);
tôi nhận được một InvalidOperationException từ một cuộc gọi nội bộ để VerifyAccess, đây là stackTrace:
bei System.Windows.Threading.Dispatcher.VerifyAccess()
bei System.Windows.Threading.DispatcherObject.VerifyAccess()
bei System.Windows.Media.Imaging.BitmapDecoder.get_IsDownloading()
bei System.Windows.Media.Imaging.BitmapFrameDecode.get_IsDownloading()
bei System.Windows.Media.Imaging.BitmapSource.FreezeCore(Boolean isChecking)
bei System.Windows.Freezable.Freeze(Boolean isChecking)
bei System.Windows.PropertyMetadata.DefaultFreezeValueCallback(DependencyObject d, DependencyProperty dp, EntryIndex entryIndex, PropertyMetadata metadata, Boolean isChecking)
bei System.Windows.Freezable.FreezeCore(Boolean isChecking)
bei System.Windows.Media.Animation.Animatable.FreezeCore(Boolean isChecking)
bei System.Windows.Freezable.Freeze()
bei System.Windows.Media.DrawingDrawingContext.DrawImage(ImageSource imageSource, Rect rectangle, AnimationClock rectangleAnimations)
bei System.Windows.Media.DrawingDrawingContext.DrawImage(ImageSource imageSource, Rect rectangle)
bei System.Windows.Media.DrawingContextDrawingContextWalker.DrawImage(ImageSource imageSource, Rect rectangle)
bei System.Windows.Media.RenderData.BaseValueDrawingContextWalk(DrawingContextWalker ctx)
bei System.Windows.Media.DrawingServices.DrawingGroupFromRenderData(RenderData renderData)
bei System.Windows.UIElement.GetDrawing()
bei System.Windows.Media.VisualTreeHelper.GetDrawing(Visual reference)
bei System.Windows.Xps.Serialization.VisualTreeFlattener.StartVisual(Visual visual)
bei System.Windows.Xps.Serialization.ReachVisualSerializer.SerializeTree(Visual visual, XmlWriter resWriter, XmlWriter bodyWriter)
bei System.Windows.Xps.Serialization.ReachVisualSerializer.SerializeObject(Object serializedObject)
bei System.Windows.Xps.Serialization.DocumentPageSerializer.SerializeChild(Visual child, SerializableObjectContext parentContext)
bei System.Windows.Xps.Serialization.DocumentPageSerializer.PersistObjectData(SerializableObjectContext serializableObjectContext)
bei System.Windows.Xps.Serialization.ReachSerializer.SerializeObject(Object serializedObject)
bei System.Windows.Xps.Serialization.DocumentPageSerializer.SerializeObject(Object serializedObject)
bei System.Windows.Xps.Serialization.DocumentPaginatorSerializer.PersistObjectData(SerializableObjectContext serializableObjectContext)
bei System.Windows.Xps.Serialization.DocumentPaginatorSerializer.SerializeObject(Object serializedObject)
bei System.Windows.Xps.Serialization.XpsSerializationManager.SaveAsXaml(Object serializedObject)
bei System.Windows.Xps.XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
bei System.Windows.Xps.XpsDocumentWriter.Write(DocumentPaginator documentPaginator)
Kể từ khi StackTrace hiện một số cuộc gọi đến BitmapSource/BitmapDecoder
, tôi nghĩ về việc cố gắng để loại bỏ các hình ảnh và thiết lập nguồn của tại chỗ Hình ảnh điều khiển null
<Image Source={x:Null} />
Sau khi tôi đã làm điều này với tất cả hình ảnh của tôi mã của tôi đã chạy trơn tru và không có ngoại lệ nào khác được kích hoạt.
tôi đã cố gắng để thực hiện một customimage để giải quyết vấn đề này như sau:
public class CustomImage : Image
{
public CustomImage()
{
this.Loaded += CustomImage_Loaded;
this.SourceUpdated += CustomImage_SourceUpdated;
}
private void CustomImage_SourceUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
{
FreezeSource();
}
private void CustomImage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
FreezeSource();
}
private void FreezeSource()
{
if (this.Source == null)
return;
var freeze = this.Source as Freezable;
if (freeze != null && freeze.CanFreeze && !freeze.IsFrozen)
freeze.Freeze();
}
}
Nhưng tôi vẫn nhận được lỗi. Ưu tiên tôi đang tìm kiếm một giải pháp hoạt động trên tất cả các hình ảnh trong ứng dụng WPF của tôi.
Hy vọng tôi đã tự làm rõ, vì điều này khá kỳ quặc để giải thích với 2 chủ đề và một ngoại lệ ngẫu nhiên tại một số điểm.
Edit: Sau một số thử nghiệm hơn nữa bây giờ tôi có thể trình bày cho bạn một ứng dụng tái sản xuất với vấn đề trước mắt, hy vọng rõ ràng của nó với điều này.
Bạn cần 3 cửa sổ, 1 thư mục và 1 hình ảnh. Trong trường hợp của tôi MainWindow.xaml Window1.XAML Window2.xaml nó
Images là tên của thư mục, và trong đó là một hình ảnh được gọi là "plus.png".
MainWindow.xaml:
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin"
Value="0,0,0,5"></Setter>
</Style>
</StackPanel.Resources>
<Button Content="Open Window 1" Click="OpenWindowInNewThread" />
<Button Content="Open Window 2" Click="OpenWindowInSameThread" />
</StackPanel>
MainWindow.xaml.cs:
private void OpenWindowInNewThread(object sender, RoutedEventArgs e)
{
var th = new Thread(() =>
{
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
var x = new Window1();
x.Closed += (s, ec) => Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
x.Show();
System.Windows.Threading.Dispatcher.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.IsBackground = true;
th.Start();
}
private void OpenWindowInSameThread(object sender, RoutedEventArgs e)
{
var x = new Window2();
x.Show();
}
Window1.XAML:
<StackPanel Orientation="Horizontal">
<ToggleButton Template="{StaticResource PlusToggleButton}" />
</StackPanel>
Window1.xaml.cs: Không có mã nào trong đó chỉ có hàm tạo ...
Window2.xaml:
<StackPanel Orientation="Horizontal">
<ToggleButton Template="{StaticResource PlusToggleButton}" />
<Button Content="Print Me" Click="Print"></Button>
</StackPanel>
Window2.xaml.cs:
public void Print(object sender, RoutedEventArgs e)
{
PrintDialog pd = new PrintDialog();
pd.PrintVisual(this, "HelloWorld");
}
App.xaml:
<ControlTemplate x:Key="PlusToggleButton"
TargetType="{x:Type ToggleButton}">
<Image Name="Image"
Source="/WpfApplication1;component/Images/plus.png"
Stretch="None" />
</ControlTemplate>
Các bước để tạo lại:
- Trong MainWindow hãy nhấp vào nút có nội dung "Mở cửa sổ 1".
- Cửa sổ sẽ bật lên trong Giao diện người dùng thứ hai thứ hai, đóng cửa sổ này.
- Nhấp vào nút nói "Open Window 2"
- Một cửa sổ sẽ bật lên trong chính UI-Thread
- Nhấn nút nói "In Me", ứng dụng sẽ sụp đổ
Hy vọng của nó bây giờ dễ dàng hơn để giúp tôi.
Edit2:
Added phần đang mất tích, xin lỗi về sai lầm này.
Thông tin khác có thể giúp giải quyết sự cố là khi bạn nhấp vào các nút theo thứ tự đảo ngược - cửa sổ thứ nhất 2 và cửa sổ 1 - và hơn cố gắng in không có ngoại lệ nào sẽ kích hoạt, vì vậy tôi vẫn tin rằng một số hình ảnh của nó vấn đề bộ nhớ đệm, rằng khi hình ảnh đầu tiên được tải vào giao diện người dùng chủ đề giao diện người dùng chính nếu nó không thành công.
Bạn có thể cố gắng để đóng băng những hình ảnh ban đầu ở nơi đầu tiên. Thay vì tải chúng từ một Uri, bạn sẽ tự lấy chúng từ web (ví dụ như một WebClient) và khởi tạo một BitmapImage từ một MemoryStream chứa bộ đệm đã tải xuống. Bạn có thể ngay lập tức đóng băng chúng sau khi tạo BitmapImage. Tất nhiên bạn cũng có thể làm điều này trong một chủ đề khác. – Clemens
Làm cách nào để tôi có thể cố định hình ảnh gốc? Điều duy nhất tôi làm là tôi chỉ định hình ảnh trong XAML với , tôi không sử dụng bất kỳ WebClient hoặc tải hình ảnh một cách không đồng bộ, tôi chỉ đơn thuần là có một cửa sổ trong một chuỗi riêng biệt hiển thị hình ảnh, khi tôi đóng cửa sổ đó và quay lại giao diện người dùng chính và cố gắng in cùng một hình ảnh bị treo. Tôi có xóa hình ảnh bằng {x: Null} mọi thứ hoạt động không. –
@Clemens quên [at] trong nhận xét cuối cùng của tôi, vui lòng xem thông báo của tôi về câu hỏi này –