Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC(同步操作方法)中的WebClient死锁 公共类HomeController:控制器 { 公共行动结果索引() { Task t=DownloadStringTaskAsync(新Uri(“http://www.google.com/search?q=aspnet")); t、 等待(); 字符串res=t.结果; 返回视图((对象)res); } 任务下载StringTaskAsync(Uri地址) { TaskCompletionSource tcs=新的TaskCompletionSource(); WebClient wc=新的WebClient(); wc.DownloadStringCompleted+=(s,e)=>tcs.SetResult(e.Result); wc.DownloadStringAsync(地址); 返回tcs.Task; } }_C#_Asp.net Mvc_Asynchronous_Task Parallel Library - Fatal编程技术网 tcs.SetResult(e.Result); wc.DownloadStringAsync(地址); 返回tcs.Task; } },c#,asp.net-mvc,asynchronous,task-parallel-library,C#,Asp.net Mvc,Asynchronous,Task Parallel Library" /> tcs.SetResult(e.Result); wc.DownloadStringAsync(地址); 返回tcs.Task; } },c#,asp.net-mvc,asynchronous,task-parallel-library,C#,Asp.net Mvc,Asynchronous,Task Parallel Library" />

C# ASP.NET MVC(同步操作方法)中的WebClient死锁 公共类HomeController:控制器 { 公共行动结果索引() { Task t=DownloadStringTaskAsync(新Uri(“http://www.google.com/search?q=aspnet")); t、 等待(); 字符串res=t.结果; 返回视图((对象)res); } 任务下载StringTaskAsync(Uri地址) { TaskCompletionSource tcs=新的TaskCompletionSource(); WebClient wc=新的WebClient(); wc.DownloadStringCompleted+=(s,e)=>tcs.SetResult(e.Result); wc.DownloadStringAsync(地址); 返回tcs.Task; } }

C# ASP.NET MVC(同步操作方法)中的WebClient死锁 公共类HomeController:控制器 { 公共行动结果索引() { Task t=DownloadStringTaskAsync(新Uri(“http://www.google.com/search?q=aspnet")); t、 等待(); 字符串res=t.结果; 返回视图((对象)res); } 任务下载StringTaskAsync(Uri地址) { TaskCompletionSource tcs=新的TaskCompletionSource(); WebClient wc=新的WebClient(); wc.DownloadStringCompleted+=(s,e)=>tcs.SetResult(e.Result); wc.DownloadStringAsync(地址); 返回tcs.Task; } },c#,asp.net-mvc,asynchronous,task-parallel-library,C#,Asp.net Mvc,Asynchronous,Task Parallel Library,操作将永远不会返回,请求将只是超时 我们对所有异步操作都使用TPL任务,在切换到Framework4.5之前,我们必须包装WebClient的一些方法 上述方法downloadstringtaskancy是其中一个包装器的简化版本 我不明白的是,为什么等待任务会使aspnet中的线程死锁,并在控制台或桌面应用程序中正常工作 下面是死锁线程的样子 请求线程 [处于睡眠、等待或加入状态] mscorlib.dll!System.Threading.Monitor.Wait(对象obj,int毫秒计时

操作将永远不会返回,请求将只是超时

我们对所有异步操作都使用TPL任务,在切换到Framework4.5之前,我们必须包装WebClient的一些方法

上述方法
downloadstringtaskancy
是其中一个包装器的简化版本

我不明白的是,为什么等待任务会使aspnet中的线程死锁,并在控制台或桌面应用程序中正常工作

下面是死锁线程的样子

请求线程 [处于睡眠、等待或加入状态]
mscorlib.dll!System.Threading.Monitor.Wait(对象obj,int毫秒计时,bool exitContext)+0x18字节 mscorlib.dll!System.Threading.ManualResetEventSlim.Wait(int毫秒计时,System.Threading.CancellationToken CancellationToken)+0x264字节
mscorlib.dll!System.Threading.Tasks.Task.InternalWait(int毫秒计时,System.Threading.CancellationToken CancellationToken)+0x166字节 mscorlib.dll!System.Threading.Tasks.Task.Wait(int毫秒计时,System.Threading.CancellationToken CancellationToken)+0x41字节
mscorlib.dll!System.Threading.Tasks.Task.Wait()+0xb字节
TCSProblem.DLL!TCSProblem.Controllers.HomeController.Index()行16+0xa字节

网络客户端线程 [处于睡眠、等待或加入状态]
mscorlib.dll!System.Threading.Monitor.Enter(对象对象对象,参考布尔锁定)+0x14字节
System.Web.dll!System.Web.AspNetSynchronizationContext.CallCallCallback(System.Threading.SendOrPostCallback回调,对象状态)+0x53字节
System.Web.dll!System.Web.AspNetSynchronizationContext.Post(System.Threading.SendOrPostCallback,对象状态)+0x9字节
System.dll!System.ComponentModel.AsyncOperation.Post(System.Threading.SendOrPostCallback,对象arg)+0x29字节
System.dll!System.Net.WebClient.PostProgressChanged(System.ComponentModel.AsyncOperation asyncOp,System.Net.WebClient.ProgressData progress)+0x25c字节


不幸的是,WebClient捕获了当前的同步上下文,并通过向其中发布来引发完成事件。正因为如此,完成操作只能在您从操作方法返回后运行,这是永远不会发生的。这意味着,你要么

  • …需要将对DownloadStringAsync的调用包装在Task.Factory.StartNew中,以便切换到没有synccontext的线程
  • …需要在调用之前将SynchronizationContext.Current设置为null,然后将其还原
  • …使用异步MVC操作

  • 默认情况下,所有.NET类都会捕获SynchronizationContext,我遇到了类似的问题:

    谢谢!我最终使用了第一种方法,2看起来太匆忙了,而3在我的情况下不是一个选项。你使用异步下载没有帮助,但有伤害。我猜这段代码是从一个更大的代码示例?FWIW中提取的,正如所写的,您可以删除't.Wait();'因为访问结果属性将被阻止,直到任务完成。
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            Task<string> t = DownloadStringTaskAsync(new Uri("http://www.google.com/search?q=aspnet"));
            t.Wait();
            string res = t.Result;
    
            return View((object)res);
        }
    
        Task<string> DownloadStringTaskAsync(Uri address)
        {
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
            WebClient wc = new WebClient();
            wc.DownloadStringCompleted += (s, e) => tcs.SetResult(e.Result);
            wc.DownloadStringAsync(address);
            return tcs.Task;
        }
    }