Асинхронно Загружая BitmapImage в C# с помощью WPF

R Внутренний

Внутренне в R функция C из функции : double rnorm (double mean, double sd) генерирует одно случайное число за раз. Когда вы вызываете свою функцию обертки R rnorm(n, mean, sd), она вызывает функцию уровня C n.

Это так же, как вы вызываете функцию уровня R только один раз с n = 1, но повторяйте ее n раз, используя replicate.

Первый метод намного быстрее (возможно, различие будет видно, когда n действительно велико), поскольку все делается на уровне C. replicate, однако, является оберткой sapply, поэтому на самом деле она не является векторизованной функцией (читается на . Действительно ли семейство «* apply» действительно не векторизовано? ).

Кроме того, если вы установите одно и то же случайное семя для обоих, вы получите тот же набор случайных чисел.


Более иллюстративный эксперимент

В моем комментарий ниже, я говорю, что случайное семя устанавливается только один раз при входе. Чтобы помочь людям понять это, я предоставляю этот пример. Нет необходимости использовать большие n. n = 4.

Сначала установим семя в 0, создав 4 стандартных нормальных образца:

set.seed(0); rnorm(4, 0, 1)
## we get
[1]  1.2629543 -0.3262334  1.3297993  1.2724293

Заметим, что в этом случае все 4 числа получены из начальное семя 0.

Теперь давайте сделаем следующее:

set.seed(0)
rnorm(2, 0, 1)
## we get
[1]  1.2629543 -0.3262334
## do not reset seed, but continue with the previous seed
replicate(2, rnorm(1, 0, 1))
## we get
[1] 1.329799 1.272429

См.?

Но если мы сбросим семя посередине, например, установите он возвращается к 0

set.seed(0)
rnorm(2, 0, 1)
## we get
[1]  1.2629543 -0.3262334
## reset seed
set.seed(0)
replicate(2, rnorm(1, 0, 1))
## we get
[1] 1.2629543 -0.3262334

Это то, что я подразумеваю под «записью».

13
задан ΩmegaMan 11 March 2019 в 18:52
поделиться

4 ответа

Принятие Вы используете привязку данных, Привязку установки . Свойство IsAsync к Истинному, кажется, стандартный способ достигнуть этого. При загрузке битового массива в коде - позади файла с помощью фонового потока +, объект Диспетчера является распространенным способом обновить UI, асинхронный

3
ответ дан 1 December 2019 в 23:49
поделиться

Чтобы уточнить ответ aku, вот небольшой пример того, где установить IsAsync:

ItemsSource="{Binding IsAsync=True,Source={StaticResource ACollection},Path=AnObjectInCollection}"

Это то, что вы будете делать в XAML.

2
ответ дан 1 December 2019 в 23:49
поделиться

Используйте или расширьте Систему. ComponentModel. BackgroundWorker:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Лично, я нахожу, что это самый легкий способ выполнить асинхронные операции в клиентских приложениях. (Я использовал это в WinForms, но не WPF. Я предполагаю, что это будет работать в WPF также.)

я обычно расширяю Backgroundworker, но Вы' не имеете к.

public class ResizeFolderBackgroundWorker : BackgroundWorker
{

    public ResizeFolderBackgroundWorker(string sourceFolder, int resizeTo)
    {
        this.sourceFolder = sourceFolder;
        this.destinationFolder = destinationFolder;
        this.resizeTo = resizeTo;

        this.WorkerReportsProgress = true;
        this.DoWork += new DoWorkEventHandler(ResizeFolderBackgroundWorker_DoWork);
    }

    void ResizeFolderBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        DirectoryInfo dirInfo = new DirectoryInfo(sourceFolder);
        FileInfo[] files = dirInfo.GetFiles("*.jpg");


        foreach (FileInfo fileInfo in files)
        {
            /* iterate over each file and resizing it */
        }
    }
}

Это - то, как Вы использовали бы его в своей форме:

    //handle a button click to start lengthy operation
    private void resizeImageButtonClick(object sender, EventArgs e)
    {
        string sourceFolder = getSourceFolderSomehow();
        resizer = new ResizeFolderBackgroundWorker(sourceFolder,290);
        resizer.ProgressChanged += new progressChangedEventHandler(genericProgressChanged);
        resizer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(genericRunWorkerCompleted);

        progressBar1.Value = 0;
        progressBar1.Visible = true;

        resizer.RunWorkerAsync();
    }

    void genericRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        progressBar1.Visible = false;
        //signal to user that operation has completed
    }

    void genericProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        //I just update a progress bar
    }
0
ответ дан 1 December 2019 в 23:49
поделиться

Я как раз изучал это, и мне пришлось бросить свои два цента, хотя через несколько лет после исходного сообщения ( на случай, если кто-то еще придет искать то же самое, что искал я).

У меня есть элемент управления Image , который должен загружать изображение в фоновом режиме с помощью Stream , а затем отображать его.

Проблема, с которой я постоянно сталкивался, заключалась в том, что BitmapSource , его источник Stream и элемент управления Image должны были находиться в одном потоке.

В этом случае использование Binding и установка IsAsynch = true вызовет исключение между потоками.

BackgroundWorker отлично подходит для WinForms, и вы можете использовать его в WPF, но я предпочитаю избегать использования сборок WinForm в WPF (раздувание проекта не рекомендуется, и это тоже хорошее практическое правило). Это должно вызвать исключение недопустимой перекрестной ссылки и в этом случае, но я его не тестировал.

Оказывается, одна строка кода выполнит любую из этих работ:

//Create the image control
Image img = new Image {HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, VerticalAlignment = System.Windows.VerticalAlignment.Stretch};

//Create a seperate thread to load the image
ThreadStart thread = delegate
     {
         //Load the image in a seperate thread
         BitmapImage bmpImage = new BitmapImage();
         MemoryStream ms = new MemoryStream();

         //A custom class that reads the bytes of off the HD and shoves them into the MemoryStream. You could just replace the MemoryStream with something like this: FileStream fs = File.Open(@"C:\ImageFileName.jpg", FileMode.Open);
         MediaCoder.MediaDecoder.DecodeMediaWithStream(ImageItem, true, ms);

         bmpImage.BeginInit();
         bmpImage.StreamSource = ms;
         bmpImage.EndInit();

         //**THIS LINE locks the BitmapImage so that it can be transported across threads!! 
         bmpImage.Freeze();

         //Call the UI thread using the Dispatcher to update the Image control
         Dispatcher.BeginInvoke(new ThreadStart(delegate
                 {
                         img.Source = bmpImage;
                         img.Unloaded += delegate 
                                 {
                                         ms.Close();
                                         ms.Dispose();
                                 };

                          grdImageContainer.Children.Add(img);
                  }));

     };

//Start previously mentioned thread...
new Thread(thread).Start();
7
ответ дан 1 December 2019 в 23:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: