기존
await Application.Current.Dispatcher.InvokeAsync(() =>
{
// ✅[1]
((System.Windows.Media.ImageBrush)this.grid_scrollviewer.Background).ImageSource = Common.ConvertBitmap(uri);
});
1단계
// ✅[1]
byte[]? imageData = await Task.Run(() =>
{
try
{
using (var wc = new System.Net.WebClient())
{
return wc.DownloadData(uri);
}
}
catch (Exception ex)
{
// skip
}
});
if (imageData == null)
{
// skip
}
// ✅[2]
// Create the BitmapImage on the UI thread.
BitmapImage? bitmap = await Application.Current.Dispatcher.InvokeAsync(() =>
{
try
{
var bmp = new BitmapImage();
using (var ms = new MemoryStream(imageData))
{
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.StreamSource = ms;
bmp.EndInit();
}
if (bmp.CanFreeze)
bmp.Freeze();
return bmp;
}
catch (Exception ex)
{
// skip
}
}, System.Windows.Threading.DispatcherPriority.Background);
if (bitmap == null)
{
return;
}
await Application.Current.Dispatcher.InvokeAsync(() =>
{
// ✅[3]
((System.Windows.Media.ImageBrush)this.grid_scrollviewer.Background).ImageSource = bitmap;
});
2단계
// Put placeholder before download
// 다운로드 시작 전에 미리 준비한 임시 화면(여기서는 null)으로 채우기
WriteableBitmap? writeableBitmap = null;
await this.Dispatcher.InvokeAsync(() =>
{
// ✅[1]
((System.Windows.Media.ImageBrush)this.grid_scrollviewer.Background).ImageSource = null;
grid_scrollviewer.Width = width;
grid_scrollviewer.Height = height;
}, System.Windows.Threading.DispatcherPriority.Send);
// ✅[2]
// Download image on Background thread
// Background thread에서 다운로드 진행
byte[]? imageData = await Task.Run(async () =>
{
try
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.Timeout = TimeSpan.FromSeconds(30);
return await httpClient.GetByteArrayAsync(uri);
}
}
catch (Exception ex)
{
// skip
}
});
if (imageData == null)
{
// skip
}
// Create a decoder and get image information on a background thread
// 디코더를 생성하고 백그라운드 스레드에서 이미지에 대한 정보 추출
BitmapImage? tempImage = null;
BitmapDecoder? decoder = null;
int pixelWidth = 0;
int pixelHeight = 0;
PixelFormat pixelFormat = PixelFormats.Bgra32;
byte[]? pixelData = null;
try
{
await Task.Run(() =>
{
try
{
using (var ms = new MemoryStream(imageData))
{
// ✅[3]
// Create a decoder to get image dimensions
// 디코더 생성
decoder = BitmapDecoder.Create(
ms,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
// Get image dimensions
// 이미지 사이즈 추출
pixelWidth = decoder.Frames[0].PixelWidth;
pixelHeight = decoder.Frames[0].PixelHeight;
// Convert to a standard format for easier processing
// FormatConvertedBitmap으로 변환
FormatConvertedBitmap convertedBitmap = new FormatConvertedBitmap(
decoder.Frames[0],
pixelFormat,
null,
0);
// Get the pixel data
int stride = (pixelWidth * pixelFormat.BitsPerPixel + 7) / 8;
pixelData = new byte[stride * pixelHeight];
convertedBitmap.CopyPixels(pixelData, stride, 0);
}
}
catch (Exception ex)
{
// skip
}
});
}
catch (Exception ex)
{
// skip
}
// 예외처리
if (pixelData == null || pixelWidth == 0 || pixelHeight == 0)
{
// skip
}
else
{
// Create and update the WriteableBitmap on the UI thread
writeableBitmap = await this.Dispatcher.InvokeAsync(() =>
{
try
{
// Create the WriteableBitmap on the UI thread
var bitmap = new WriteableBitmap(
pixelWidth,
pixelHeight,
96, 96, // Default DPI
pixelFormat,
null);
// Update the bitmap with our pixel data
int stride = (pixelWidth * pixelFormat.BitsPerPixel + 7) / 8;
bitmap.WritePixels(
new Int32Rect(0, 0, pixelWidth, pixelHeight),
pixelData,
stride,
0);
if (bitmap.CanFreeze)
bitmap.Freeze();
return bitmap;
}
catch (Exception ex)
{
// skip
}
}, System.Windows.Threading.DispatcherPriority.Background);
}
// Apply the bitmap on a low-priority UI operation
BitmapSource? finalBitmap = writeableBitmap != null ? (BitmapSource)writeableBitmap : (BitmapSource)tempImage;
if (finalBitmap != null)
{
await this.Dispatcher.InvokeAsync(() =>
{
var imageBrush = (System.Windows.Media.ImageBrush)this.grid_scrollviewer.Background;
// Apply RenderOptions to the brush
RenderOptions.SetBitmapScalingMode(imageBrush, BitmapScalingMode.HighQuality);
// Set the image source
imageBrush.ImageSource = finalBitmap;
}, System.Windows.Threading.DispatcherPriority.Background);
}