2016-12-11 5 views
1

ファイル拡張子とBitMapSourceオブジェクトの辞書を含む静的クラスがあります。そのクラスには、関連するBitMapSourceオブジェクトがFileInfoオブジェクトで返され、まだ辞書にない場合は取得して辞書に戻してから返す関数が含まれています。
これはGUIスレッドから実行するとうまく動作します。しかし、バックグラウンドスレッドに入れようとすると、何も戻ってこない。バックグラウンドスレッドからこれを実行できないようにすべき理由はありますか?静的クラスを使用した非同期関数

静的クラス

namespace Test.Classes 
{ 
    using System.Collections.Generic; 
    using System.Drawing; 
    using System.IO; 
    using System.Windows; 
    using System.Windows.Interop; 
    using System.Windows.Media.Imaging; 

    public static class IconMap 
    { 
    private static Dictionary<string, BitmapSource> iconDictionary = new Dictionary<string, BitmapSource>(); 

    public static BitmapSource GetFileIcon(FileInfo fileInfo) 
    { 
     if (iconDictionary.ContainsKey(fileInfo.Extension)) 
     { 
     return iconDictionary[fileInfo.Extension]; 
     } 
     else 
     { 
     lock (iconDictionary) 
     { 
      Icon icon = Icon.ExtractAssociatedIcon(fileInfo.FullName); 
      BitmapSource bitMapSource = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, new Int32Rect(0, 0, icon.Width, icon.Height), BitmapSizeOptions.FromEmptyOptions()); 
      iconDictionary.Add(fileInfo.Extension, bitMapSource); 
      return bitMapSource; 
     } 
     } 
    } 
    } 
} 

Control.cs

namespace Test.Controls 
{ 
    using System; 
    using System.Diagnostics; 
    using System.IO; 
    using System.Threading.Tasks; 
    using System.Windows.Controls; 
    using System.Windows.Input; 
    using System.Windows.Media.Imaging; 
    using Microsoft.Office.Interop.Outlook; 

    public partial class AttachedFileInfo : UserControl 
    { 
    private FileInfo file; 

    public AttachedFileInfo(FileInfo fileInfo) 
    { 
     this.InitializeComponent(); 
     this.file = fileInfo; 

     this.FileLink.NavigateUri = new Uri(fileInfo.FullName); 
     this.FileName.Text = fileInfo.Name; 
     this.LoadFileIcon(fileInfo); 
    } 

    private async void LoadFileIcon(FileInfo fileInfo) 
    { 
     Task<BitmapSource> getFileIconTask = Task<BitmapSource>.Factory.StartNew(() => 
     { 
     // If I change this to BitmapSource icon = null; it works as expected. 
     BitmapSource icon = Classes.IconMap.GetFileIcon(fileInfo); 
     return icon; 
     }); 
     await getFileIconTask; 

     this.FileIcon.Source = Classes.IconMap.GetFileIcon(fileInfo); 
     // getFileIconTask.Result; 
    } 

    private void FileLink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) 
    { 
     Process.Start(this.file.FullName); 
    } 
    } 
} 
+2

辞書から同時に読み書きすることは安全ではありません。 'ConcurrentDictionary'を使うか、' ReaderWriterLockSlim'でアクセスをラップして、書き込み中に並行読者をブロックしてください。 –

+0

ありがとうございます。私はConcurrentDictionaryオブジェクトを認識していませんでした。私は辞書を変更してAddをTryAddに変更しましたが、問題を解決できないようです。 – JtM

+0

BitmapSourceはDependencyObjectです。つまり、BitmapSourceは、それを作成したスレッドによってのみ使用できます。 –

答えて

2

彼らは.Freeze()メソッドを呼び出すことによって凍結されている場合WPFリソースは、別のスレッドからのみを使用することができますので、あなたのアイコンが(参照、表示されません。コード蛇腹)。

もう1つの問題は、ConcurrentDictionaryを使用してもGetFileIcon()メソッドがスレッドセーフではないことです.bacaseでは、アイコンがiconDictionaryにアイコンを追加し、ロックされたコードブロックを残したときに、同じファイルタイプのアイコンを辞書に追加すると、ArgumentExceptionが発生します。したがって、ロック内では、特定の拡張子のアイコンが辞書にまだ存在していないかどうかを再度テストする必要があります。

private static ConcurrentDictionary<string, BitmapSource> iconDictionary = new ConcurrentDictionary<string, BitmapSource>(); 

public static BitmapSource GetFileIcon(FileInfo fileInfo) 
{ 
    BitmapSource bitMapSource; 
    if (iconDictionary.TryGetValue(fileInfo.Extension, out bitMapSource)) 
    { 
     return bitMapSource; 
    } 
    else 
    { 
     lock (iconDictionary) 
     { 
      if (iconDictionary.TryGetValue(fileInfo.Extension, out bitMapSource)) 
       return bitMapSource; 

      Icon icon = Icon.ExtractAssociatedIcon(fileInfo.FullName); 
      bitMapSource = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, new Int32Rect(0, 0, icon.Width, icon.Height), BitmapSizeOptions.FromEmptyOptions()); 
      bitMapSource.Freeze();//Allows BitmapSource to be used on another thread 
      iconDictionary[fileInfo.Extension] = bitMapSource; 
      return bitMapSource; 
     } 
    } 
} 
+0

ありがとうございます。私は私の髪を引き裂いていた、と私は多くを開始する必要はありませんでした。 – JtM

関連する問題