我正在尝试将网络服务器中的图像加载到pictureBox中。为了不阻止表格,直到图片被加载我开始一个新的线程,它在LoadPicture() - 函数上工作,直到所有工作完成。
所有内容都将在MouseHover-Event上启动,因此可以在短时间内多次触发,因为默认的WindowsHoverTime是180ms并且无法更改(我在那里搜索了很多)。 这是功能:
public void LoadPicture(string url)
{
try
{
WebRequest req = HttpWebRequest.Create(url);
req.Timeout = 3500;
req.Method = "HEAD";
using (WebResponse resp = req.GetResponse())
{
int ContentLength;
if (int.TryParse(resp.Headers.Get("Content-Length"), out ContentLength))
{
string ContentType = resp.Headers.Get("Content-Type");
if (ContentLength < 1048576 && ContentType == "image/png")
{
this.pictureBox1.Load(url);
}
else
{
this.pictureBox1.Image = mainprogram.Properties.Resources.sample;
}
}
}
}
catch { this.pictureBox1.Image = mainprogram.Properties.Resources.sample; }
}
如果url包含一个小于1MB的png文件,则应将其加载到pictureBox1中,否则,将加载资源中的deafult图像。
线程和调用:
namespace mainprogram
{
public partial class Form1 : Form
{
Thread threadworker;
.
.
.
private void button1_MouseHover(object sender, EventArgs e)
{
if (threadworker.IsAlive == false)
{
threadworker = new Thread(() => LoadPicture(url));
threadworker.Start();
}
}
现在出现问题:线程几乎一直都会失败。 Catch {}将执行9/10次。主要是在WebResponse resp = req.GetResponse()崩溃。如果我在同一个线程中使用该函数(不启动新的),它将加载正常,但GUI将停止响应3秒,直到图片被加载。
编辑:它有时会工作,所以我不确定我做错了什么。
答案 0 :(得分:0)
async
举例说明SLaks优秀评论,这是MSDN上如何使用async / await for web http://msdn.microsoft.com/en-us/library/hh300224.aspx#BKMK_ConvertGtBtArr
的漫步对this answer to a similar question上async / await的工作方式和好处进行了大量解释。
还有一个GetResponse
的异步版本可用于.NET 4.0(及更低版本),称为BeginGetResponse
。它记录在MSDN http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.100).aspx上,但该页面上的示例很糟糕,因为它阻止了使用事件。你想要的是在UI线程中调用你的回调。 async
/ await
会自动执行此操作。使用回调,您可能必须手动将回调推迟到UI syncContext。
无论如何,所有这些只有在实际问题是访问冲突时才有用,因为您尝试在非UI线程中绘制所请求的图像和/或阻止UI。如果GetResponse
因DNS问题而引发异常,错误403/404,超时或类似情况,您应该投资找出原因。
答案 1 :(得分:0)
经过大量的研究和麻烦,我得到了它的工作。 首先,我要感谢SLaks的评论。我使用了async / await + GetResponseAsync,它完美无缺:
public async void LoadPicture(string url)
{
bool worker = await GetURLContentsAsync(url);
}
private async Task<bool> GetURLContentsAsync(string url)
{
var webReq = (HttpWebRequest)WebRequest.Create(url);
using (WebResponse response = await webReq.GetResponseAsync())
{
.
.
.
不幸的是,GetResponseAsync仅在.NET Framework 4.5中可用,因此我尝试使用与此处不同的BeginGetResponse方法: https://www.informit.com/guides/content.aspx?g=dotnet&seqNum=583 但它阻止了UI线程(非异步)或者无法加载图片3/4次(相同的图像)。
所以我最终再次使用线程:
private void LoadPicture(string url)
{
threadworker = new Thread(() => pictureBox1.Image = getImgFromUrl(url));
threadworker.Start();
}
public Bitmap getImgFromUrl(string url)
{
Bitmap bmp = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
try
{
bmp = new Bitmap(response.GetResponseStream());
.
.
.
正如你所看到的,它几乎与问题帖子中的代码相同,我发现threadworker.IsAlive是罪魁祸首,pictureBox1.Load()比将流写入临时BitMap文件需要更长的时间然后加载它。