Home > Blockchain >  How to instantly cancell a function in wpf
How to instantly cancell a function in wpf

Time:10-22

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;

        }
  • Related