2015-11-04 44 views
2

在visual studio 2015社區中使用c#,嘗試將轉換base64編碼字符串的代碼轉換爲線程化任務以減少瓶頸。c#在setter中的線程

這是工作的代碼:

private string _logoBase64; 
    public string logoBase64 
    { 
     get { return _logoBase64; } 
     set 
     { 
      _logoBase64 = value; 
      setLogo(); 
     } 
    } 
    public ImageSource logo { get; set; } 
      private void setLogo() 
    { 
     if ((this.logoBase64 != null) && (this.logoBase64.Length > 0)) 
     { 
      string _logoBase64 = this.logoBase64 
       .Replace("data:image/png;base64,", "") 
       .Replace("data:image/gif;base64,", "") 
       .Replace("data:image/jpeg;base64,", ""); 
      var image = new BitmapImage(); 
      try 
      { 
       image.BeginInit(); 
       image.StreamSource = new MemoryStream(Convert.FromBase64String(_logoBase64)); 
       image.EndInit(); 
       this.logo = image; 
      } 
      catch (Exception e) 
      { 
       Program.Errors.Add(e.Message + "\n" + e.StackTrace); 
       if (Program.environment == "development") 
       { 
        Console.WriteLine(e.Message); 
       } 
      } 
     } 
    } 

使用this例如,我試圖將其轉換爲一個線程任務:

internal Task setLogoASync(string b64, CancellationToken cancellationToken) 
    { 
     return Task.Run(() => 
     { 
      var image = new BitmapImage(); 
      if ((b64 != null) && (b64.Length > 0)) 
      { 
       b64 = b64 
        .Replace("data:image/png;base64,", "") 
        .Replace("data:image/gif;base64,", "") 
        .Replace("data:image/jpeg;base64,", ""); 

       try 
       { 
        image.BeginInit(); 
        image.StreamSource = new MemoryStream(Convert.FromBase64String(b64)); 
        image.EndInit(); 
        this.logo = image; 
       } 
       catch (Exception e) 
       { 
        Program.Errors.Add(e.Message + "\n" + e.StackTrace); 
        if (Program.environment == "development") 
        { 
         Console.WriteLine(e.Message); 
        } 
       } 
      } 
      this.logo = image; 
     }, cancellationToken); 
    } 

但問題是二傳手必須是異步,但它不可能。有沒有解決的辦法?

+11

的制定者通常的建議是,他們應該只用於非常短的運行操作之前。最好是完全刪除它,只是提供一個公共方法 – thumbmunkeys

+1

你可以在setter中使用線程或BackgroundWorker,並讓setter繼續而不停止你的GUI –

+0

Saad Mind告訴我到底如何? – pgee70

回答

2

對setter的一般建議是,它們只能用於非常短的運行操作。

最好將其完全刪除,而只是提供一個公共方法。

原因是作爲一名程序員,我不應該考慮調用setter的意外影響和副作用。

讓setter創建一個線程就計算時間和所用資源(例如CPU和內存)而言是一種意想不到的暗示。

2

每次修改圖像時,都不要試圖計算Base64實現,而是使用Lazy<T>在第一次實際請求時計算它。

private Lazy<ImageSource > _image; 
public ImageSource logo 
{ 
    get { return _image.Value; } 
} 

private string _logoBase64; 
public string logoBase64 
{ 
    get { return _logoBase64; } 
    set 
    { 
     _logoBase64 = value; 
     //Can't reset a Lazy, so we create a new one. 
     _image=new Lazy<ImageSource>(()=>imageFromBase64())); 
    } 
} 

//Initialize the Lazy in the constructor 
public MyClass() 
{ 
    _image=new Lazy<ImageSource>(()=>imageFromBase64())l 
} 

ImageSource imageFromBase64() 
{ 
    var image = new BitmapImage(); 
    if ((b64 != null) && (b64.Length > 0)) 
    { 
      b64 = b64 
       .Replace("data:image/png;base64,", "") 
       .Replace("data:image/gif;base64,", "") 
       .Replace("data:image/jpeg;base64,", ""); 

      try 
      { 
       image.BeginInit(); 
       image.StreamSource = new MemoryStream(Convert.FromBase64String(b64)); 
       image.EndInit(); 
      } 
      catch (Exception e) 
      { 
       Program.Errors.Add(e.Message + "\n" + e.StackTrace); 
       if (Program.environment == "development") 
       { 
        Console.WriteLine(e.Message); 
       } 
      } 
    } 
    return image; 
} 

爲了避免延誤即使是第logo請求時,你可以在一個一次性的任務發起慵懶的評價。懶惰保證其內容的併發訪問,因此並不重要任務是否完成或不會有人請求標誌

public string logoBase64 
{ 
    get { return _logoBase64; } 
    set 
    { 
     _logoBase64 = value; 
     //Can't reset a Lazy, so we create a new one. 
     var newLazy=new Lazy<ImageSource>(()=>imageFromBase64())); 
     //Start throwaway task before assigning to backing field, 
     //to avoid race conditions 
     Task.Run(()=>newLazy.Value); 
     _image=newLazy; 
    } 
} 
+0

這是一個好主意,但提供的代碼不起作用,我看不到如何解決它。 private Lazy _image = new Lazy (()=> imageFromBase64()); =一個字段初始值設定項不能引用非靜態字段,方法或屬性'User.ImageFromBae64() – pgee70

+0

在你的構造函數中初始化它。 –

+0

謝謝你做到了。 – pgee70