0

これが私の問題です。
BlockingCollection にいくつかの BitmapImages をロードしています

    public void blockingProducer(BitmapImage imgBSource)
    {
        if (!collection.IsAddingCompleted)
            collection.Add(imgBSource);
    }

読み込みはバックグラウンドワーク スレッドで行われます。

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        String filepath; int imgCount = 0;

        for (int i = 1; i < 10; i++)
        {
            imgCount++;

            filepath = "Snap";
            filepath += imgCount;
            filepath += ".bmp";

            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                label1.Content = "Snap" + imgCount + " loaded.";
            }), DispatcherPriority.Normal);

            BitmapImage imgSource = new BitmapImage();
            imgSource.BeginInit();
            imgSource.UriSource = new Uri(filepath, UriKind.Relative);
            imgSource.CacheOption = BitmapCacheOption.OnLoad;
            imgSource.EndInit();

            blockingProducer(imgSource);
        }
    }

コードのこの部分をデバッグするとすべて問題ないように見えますが、問題は今発生しています...

画像の読み込みが完了したら、UI に 1 つずつ表示したいと思います。そのためにディスパッチャーを使用していますが、呼び出されたスレッドは別のスレッドに属しているため、オブジェクトにアクセスできないというメッセージが常に表示されます。

    public void display(BlockingCollection<BitmapImage> results)
    {
        foreach (BitmapImage item in collection.GetConsumingEnumerable())
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                this.dstSource.Source = item;
                Thread.Sleep(250);
            }), DispatcherPriority.Background);
        }
    }

デバッグは、エラーがここにあると非難します

                this.dstSource.Source = item;

私はすべてを試していますが、何が間違っているのかわかりません。誰でも何か考えがありますか?

4

2 に答える 2

1

Freeze他のスレッドからアクセスできるようにするには、画像を読み込んだ後に呼び出す必要があります。

BitmapImage imgSource = new BitmapImage();
imgSource.BeginInit();
imgSource.UriSource = new Uri(filepath, UriKind.Relative);
imgSource.CacheOption = BitmapCacheOption.OnLoad;
imgSource.EndInit();
imgSource.Freeze(); // here

私がフラグを理解しているBitmapCacheOption.OnLoad限り、BitmapImage がストリームからロードされた場合にのみ有効です。BitmapCacheOptionの備考セクションには、次のように記載されています。

BitmapImage の作成に使用されたストリームを閉じたい場合は、CacheOption を BitmapCacheOption.OnLoad に設定します。デフォルトの OnDemand キャッシュ オプションは、イメージが必要になるまでストリームへのアクセスを保持し、クリーンアップはガベージ コレクターによって処理されます。

Uri から作成された BitmapImage は、非同期にロードできます (IsDownloadingプロパティを参照してください)。したがって、FreezeEndInit の後もダウンロードがまだ進行中の可能性があるため、このような BitmapImage では呼び出すことができない場合があります。それにもかかわらず、ファイル Uris から BitmapImages をロードしているため、それはあなたの場合でも機能すると思います。これはすぐに行われるようです。

この潜在的な問題を回避するには、FileStream から BitmapImage を作成するだけです。

var imgSource = new BitmapImage();

using (var stream = new FileStream(filepath, FileMode.Open))
{
    imgSource.BeginInit();
    imgSource.StreamSource = stream;
    imgSource.CacheOption = BitmapCacheOption.OnLoad;
    imgSource.EndInit();
    imgSource.Freeze();
}
于 2013-04-18T05:34:17.297 に答える
0

今後の読者のために、私が問題を解決するために使用したコードを次に示します。

    public void display(BlockingCollection<BitmapImage> collection)
    {
        if (collection.IsCompleted || collection.Count != 0)
        {
            BitmapImage item = collection.Take();
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                this.dstSource.Source = item;

            }), DispatcherPriority.Normal);
        }
        else
        {
            dispatcherTimer.Stop();
        }
    }

    public void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        display(collection);
    }

    public void configureDispatcherTimer()
    {
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        TimeSpan interval = TimeSpan.FromMilliseconds(150);
        dispatcherTimer.Interval = interval;
    }
于 2013-04-18T19:13:13.293 に答える