在visual studio 2015社区中使用c#,尝试将将base64编码的字符串转换为图像的代码转换为线程化任务,以减少瓶颈。
这是有效的代码:
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);
}
但问题是setter必须是异步的,但它不可能。有办法解决这个问题吗?
答案 0 :(得分:2)
setter的一般建议是它们只应用于非常短的运行操作。
最好完全删除它,而只是提供一个公共方法。
原因在于,作为程序员,我不需要考虑调用setter的意外影响和副作用。
让setter创建一个线程在计算时间和使用的资源(例如CPU和内存)方面是一个意想不到的暗示。
答案 1 :(得分: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
请求的延迟,您可以在一次性任务中启动延迟评估。 Lazy确保对其内容的并发访问,因此在有人请求徽标之前,任务是否完成无关紧要
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;
}
}