Im trying to stop a function that loads images to a combobox but when i want to cancell, it takes a lot of time, it always downlod images from a server so the connection can fail, when it happens i cancell the process with a cancellation token but it still "working" inclusive when i cancell the token. tose are my functions:
private async Task FillModels()
{
var token = comboBox_utils._cancellSource = new();
try
{
await comboBox_utils.FillModelList(cb_model_list, _downloadedModels, new Size(500, 180), token.Token);
}
catch
{
comboBox_utils._isLoadingModels = false;
MessageBox.Show("Cancelado");
}
}
public async Task FillModelList(ComboBox cb, List<DefaultModelDropdown> modelList,
Size size, CancellationToken cancell)
{
if (_isLoadingModels) { return; }
_isLoadingModels = true;
Visor_de_imágenes.CheckConection.CheckConection check = new();
int amountDownloadedModels = modelList.Count;
//crea los modelos faltantes
DefaultModelDropdown dropdownContent = new();
List<modelo> xmlModels = xml.Serialize_xml(xml.getXmlFolder());
int amountModels = xmlModels.Count;
if (amountDownloadedModels == amountModels) { return; }
int amountListbox = cb.Items.Count;
for (int i = amountListbox; i < amountModels; i )
{
try
{
var model = await Task.Run(async () => { return await dropdownContent.NewDedfaultModel(xmlModels[i], cancell); }, cancell);
if (cancell.IsCancellationRequested)
{
cancell.ThrowIfCancellationRequested();
}
modelList.Add(model);
cb.Items.Add(panel.CreatePanelModel(model, size));
}
catch
{
break;
}
}
_isLoadingModels = false;
}
public async Task<DefaultModelDropdown> NewDedfaultModel(modelo model, CancellationToken cancell)
{
var io = new Image_options();
var def = new DefaultModelDropdown();
def.Name = model.nombre;
def.extra = model.nombre_clave;
BitmapImage bi;
try
{
bi = await io.AsyncPathToImage(model.imagen, cancell);
}catch
{
bi = new();
}
def.image = bi;
return def;
}
public async Task<BitmapImage> AsyncPathToImage(string path, CancellationToken cancell = default)
{
return await Task.Run(() =>
{
BitmapImage bi = new(new Uri(path, UriKind.RelativeOrAbsolute));
bi.Freeze();
return bi;
},cancell);
}
i dont know why it takes like 5 or 10 secs after get cancelled.
CodePudding user response:
A cancellable method to load a BitmapSource from a file might look like this:
public static async Task<BitmapSource> LoadBitmapSourceAsync(
string path, CancellationToken cancellationToken)
{
using var fileStream = File.OpenRead(path);
using var memoryStream = new MemoryStream();
try
{
await fileStream.CopyToAsync(memoryStream, cancellationToken);
}
catch (OperationCanceledException ex)
{
return null;
}
memoryStream.Position = 0;
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
Or a bit shorter with creating a BitmapFrame instead of a BitmapImage:
public static async Task<BitmapSource> LoadBitmapSourceAsync(
string path, CancellationToken cancellationToken)
{
using var fileStream = File.OpenRead(path);
using var memoryStream = new MemoryStream();
try
{
await fileStream.CopyToAsync(memoryStream, cancellationToken);
}
catch (OperationCanceledException ex)
{
return null;
}
memoryStream.Position = 0;
return BitmapFrame.Create(
memoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
CodePudding user response:
I made this and it works :
public async Task<BitmapImage> AsyncPathToImage(string path, CancellationToken cancell = default)
{
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
var memoryStream = new MemoryStream();
await fileStream.CopyToAsync(memoryStream,cancell);
memoryStream.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}