C# 使用新线程从web加载图像

C# 使用新线程从web加载图像,c#,multithreading,visual-studio-2013,webrequest,system.net,C#,Multithreading,Visual Studio 2013,Webrequest,System.net,我正在尝试将图像从Web服务器加载到pictureBox中。为了在图片加载之前不阻塞表单,我启动了一个新线程,该线程在LoadPicture()函数上工作,直到所有工作完成 所有内容都将在MouseHover事件中启动,因此它可以在短时间内被触发多次,因为默认的WindowsHoverTime为180ms,并且无法更改(我在这方面搜索了很多)。 这就是功能: public void LoadPicture(string url) { try { WebReques

我正在尝试将图像从Web服务器加载到pictureBox中。为了在图片加载之前不阻塞表单,我启动了一个新线程,该线程在LoadPicture()函数上工作,直到所有工作完成

所有内容都将在MouseHover事件中启动,因此它可以在短时间内被触发多次,因为默认的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; }
}
现在问题是:线程几乎总是会失败。捕获{}将执行9/10次。大多数情况下,WebResponse resp=req.GetResponse()会崩溃。如果我在同一个线程中使用该函数(不启动新线程),它将正常加载,但GUI将停止响应大约3秒钟,直到加载图片

编辑:它有时确实有效,所以我不确定我做错了什么。

使用
async
为了举例说明SLaks的优秀评论,下面是一个关于MSDN如何在web上使用async/await的演练

还有很多关于async/await on的工作原理和优点的解释

使用.NET4.0 还有一个异步版本的
GetResponse
可用于.NET 4.0(及更低版本),名为
BeginGetResponse
。它在MSDN上有文档记录,但该页面上的示例非常可怕,因为它阻止使用事件。您想要的是在UI线程中调用回调<代码>异步/
等待
自动执行。使用回调时,您可能必须手动将回调延迟到UI syncContext

评论
无论如何,所有这些只有在实际问题是访问冲突时才有用,因为您试图在非UI线程中绘制请求的图像和/或阻塞UI。如果由于DNS问题、错误403/404、超时或类似原因而引发异常,那么您应该投入精力找出原因。

好的,经过大量研究和麻烦,我让它工作了。 首先我要感谢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())
    {
        .
        .
        .

正如您所看到的,这段代码与问题帖子中的代码几乎相同,我发现threadworker.IsAlive是罪魁祸首,pictureBox1.Load()是罪魁祸首比将流写入临时位图文件并随后加载要花费更长的时间。

您会遇到什么异常?您应该使用async with
HttpClient
而不是线程。由于我使用try&catch,它将失败并触发catch{} phrase@SLaks你能举个简单的例子吗?不幸的是,
HttpClient
只能在.NET 4.5中使用。我精简了我的应用程序以使用4.0,因为很多用户不想安装新的.NET Framework。有没有不需要4.5的解决方案?
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())
    {
        .
        .
        .
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());
            .
            .
            .