NewLife/X

Task.Yield会导致强制捕获上下文,虽然会在另一个线程执行,但在UI线程中可能无法抢占上下文导致死锁
大石头 编写于 2019-07-10 15:21:23
共计: 修改7个文件,增加27行、删除26行。
修改 +1 -1
修改 +6 -6
修改 +10 -9
修改 +2 -2
修改 +2 -2
修改 +2 -2
修改 +4 -4
修改 +1 -1
diff --git a/NewLife.Core/Collections/ICluster.cs b/NewLife.Core/Collections/ICluster.cs
index b0fae7a..dc18d0e 100644
--- a/NewLife.Core/Collections/ICluster.cs
+++ b/NewLife.Core/Collections/ICluster.cs
@@ -66,7 +66,7 @@ namespace NewLife.Collections
             try
             {
                 item = cluster.Get();
-                return await func(item);
+                return await func(item).ConfigureAwait(false);
             }
             finally
             {
修改 +6 -6
diff --git a/NewLife.Core/Http/TinyHttpClient.cs b/NewLife.Core/Http/TinyHttpClient.cs
index 6bbca13..88119e7 100644
--- a/NewLife.Core/Http/TinyHttpClient.cs
+++ b/NewLife.Core/Http/TinyHttpClient.cs
@@ -87,7 +87,7 @@ namespace NewLife.Http
 #if NET4
                 tc.Connect(remote.Address, remote.Port);
 #else
-                await tc.ConnectAsync(remote.Address, remote.Port);
+                await tc.ConnectAsync(remote.Address, remote.Port).ConfigureAwait(false);
 #endif
 
                 Client = tc;
@@ -95,7 +95,7 @@ namespace NewLife.Http
             }
 
             // 发送
-            if (request != null) await request.CopyToAsync(ns);
+            if (request != null) await request.CopyToAsync(ns).ConfigureAwait(false);
 
             // 接收
             var buf = new Byte[64 * 1024];
@@ -104,7 +104,7 @@ namespace NewLife.Http
 #else
             var source = new CancellationTokenSource(Timeout);
 
-            var count = await ns.ReadAsync(buf, 0, buf.Length, source.Token);
+            var count = await ns.ReadAsync(buf, 0, buf.Length, source.Token).ConfigureAwait(false);
 #endif
 
             return new Packet(buf, 0, count);
@@ -124,7 +124,7 @@ namespace NewLife.Http
             StatusCode = -1;
 
             // 发出请求
-            var rs = await SendDataAsync(uri, req);
+            var rs = await SendDataAsync(uri, req).ConfigureAwait(false);
             if (rs == null || rs.Count == 0) return null;
 
             // 解析响应
@@ -133,7 +133,7 @@ namespace NewLife.Http
             // 头部和主体分两个包回来
             if (rs != null && rs.Count == 0 && ContentLength != 0)
             {
-                rs = await SendDataAsync(null, null);
+                rs = await SendDataAsync(null, null).ConfigureAwait(false);
             }
 
             // chunk编码
@@ -357,7 +357,7 @@ namespace NewLife.Http
             var client = pool.Get();
             try
             {
-                return (await client.SendAsync(uri, null))?.ToStr();
+                return (await client.SendAsync(uri, null).ConfigureAwait(false))?.ToStr();
             }
             finally
             {
修改 +10 -9
diff --git a/NewLife.Core/Remoting/ApiClient.cs b/NewLife.Core/Remoting/ApiClient.cs
index f93fa4d..afe5010 100644
--- a/NewLife.Core/Remoting/ApiClient.cs
+++ b/NewLife.Core/Remoting/ApiClient.cs
@@ -172,8 +172,9 @@ namespace NewLife.Remoting
         public virtual async Task<Object> InvokeAsync(Type resultType, String action, Object args = null, Byte flag = 0)
         {
             // 让上层异步到这直接返回,后续代码在另一个线程执行
+            //!!! Task.Yield会导致强制捕获上下文,虽然会在另一个线程执行,但在UI线程中可能无法抢占上下文导致死锁
 #if !NET4
-            await Task.Yield();
+            //await Task.Yield();
 #endif
 
             Open();
@@ -182,16 +183,16 @@ namespace NewLife.Remoting
 
             try
             {
-                return await ApiHostHelper.InvokeAsync(this, this, resultType, act, args, flag);
+                return await ApiHostHelper.InvokeAsync(this, this, resultType, act, args, flag).ConfigureAwait(false);
             }
             catch (ApiException ex)
             {
                 // 重新登录后再次调用
                 if (ex.Code == 401)
                 {
-                    await Cluster.InvokeAsync(client => OnLoginAsync(client, true));
+                    await Cluster.InvokeAsync(client => OnLoginAsync(client, true)).ConfigureAwait(false);
 
-                    return await ApiHostHelper.InvokeAsync(this, this, resultType, act, args, flag);
+                    return await ApiHostHelper.InvokeAsync(this, this, resultType, act, args, flag).ConfigureAwait(false);
                 }
 
                 throw;
@@ -212,7 +213,7 @@ namespace NewLife.Remoting
         public virtual async Task<TResult> InvokeAsync<TResult>(String action, Object args = null, Byte flag = 0)
         {
             // 发送失败时,返回空
-            var rs = await InvokeAsync(typeof(TResult), action, args, flag);
+            var rs = await InvokeAsync(typeof(TResult), action, args, flag).ConfigureAwait(false);
             if (rs == null) return default;
 
             return (TResult)rs;
@@ -226,7 +227,7 @@ namespace NewLife.Remoting
         public virtual TResult Invoke<TResult>(String action, Object args = null, Byte flag = 0)
         {
             // 发送失败时,返回空
-            var rs = InvokeAsync(typeof(TResult), action, args, flag).Result;
+            var rs = TaskEx.Run(() => InvokeAsync(typeof(TResult), action, args, flag)).Result;
             if (rs == null) return default;
 
             return (TResult)rs;
@@ -258,7 +259,7 @@ namespace NewLife.Remoting
         {
             var act = action;
 
-            return (TResult)await ApiHostHelper.InvokeAsync(this, client, typeof(TResult), act, args, flag);
+            return (TResult)await ApiHostHelper.InvokeAsync(this, client, typeof(TResult), act, args, flag).ConfigureAwait(false);
         }
 
         Task<IMessage> IApiSession.SendAsync(IMessage msg) => Cluster.InvokeAsync(client => client.SendMessageAsync(msg)).ContinueWith(t => t.Result as IMessage);
@@ -286,10 +287,10 @@ namespace NewLife.Remoting
         public virtual async Task<Object> LoginAsync()
         {
 #if !NET4
-            await Task.Yield();
+            //await Task.Yield();
 #endif
 
-            return await Cluster.InvokeAsync(client => OnLoginAsync(client, false));
+            return await Cluster.InvokeAsync(client => OnLoginAsync(client, false)).ConfigureAwait(false);
         }
         #endregion
 
修改 +2 -2
diff --git a/NewLife.Core/Remoting/ApiNetServer.cs b/NewLife.Core/Remoting/ApiNetServer.cs
index effb24b..fa7b601 100644
--- a/NewLife.Core/Remoting/ApiNetServer.cs
+++ b/NewLife.Core/Remoting/ApiNetServer.cs
@@ -96,9 +96,9 @@ namespace NewLife.Remoting
         /// <param name="args">参数</param>
         /// <param name="flag">标识</param>
         /// <returns></returns>
-        public async Task<TResult> InvokeAsync<TResult>(String action, Object args = null, Byte flag = 0) => (TResult)await ApiHostHelper.InvokeAsync(_Host, this, typeof(TResult), action, args, flag);
+        public async Task<TResult> InvokeAsync<TResult>(String action, Object args = null, Byte flag = 0) => (TResult)await ApiHostHelper.InvokeAsync(_Host, this, typeof(TResult), action, args, flag).ConfigureAwait(false);
 
-        async Task<IMessage> IApiSession.SendAsync(IMessage msg) => await Session.SendMessageAsync(msg) as IMessage;
+        async Task<IMessage> IApiSession.SendAsync(IMessage msg) => await Session.SendMessageAsync(msg).ConfigureAwait(false) as IMessage;
 
         Boolean IApiSession.Send(IMessage msg) => Session.SendMessage(msg);
     }
修改 +2 -2
diff --git a/NewLife.Core/Remoting/IApiHost.cs b/NewLife.Core/Remoting/IApiHost.cs
index 7a3cd36..721b338 100644
--- a/NewLife.Core/Remoting/IApiHost.cs
+++ b/NewLife.Core/Remoting/IApiHost.cs
@@ -80,9 +80,9 @@ namespace NewLife.Remoting
             try
             {
                 if (session is IApiSession ss)
-                    rs = await ss.SendAsync(msg);
+                    rs = await ss.SendAsync(msg).ConfigureAwait(false);
                 else if (session is ISocketRemote client)
-                    rs = (await client.SendMessageAsync(msg)) as IMessage;
+                    rs = (await client.SendMessageAsync(msg).ConfigureAwait(false)) as IMessage;
                 else
                     throw new InvalidOperationException();
 
修改 +2 -2
diff --git a/NewLife.Core/Yun/Map.cs b/NewLife.Core/Yun/Map.cs
index bb9fe5b..989c370 100644
--- a/NewLife.Core/Yun/Map.cs
+++ b/NewLife.Core/Yun/Map.cs
@@ -131,7 +131,7 @@ namespace NewLife.Yun
             LastString = null;
             LastKey = key;
 
-            var rs = await _Client.DownloadStringAsync(url);
+            var rs = await _Client.DownloadStringAsync(url).ConfigureAwait(false);
 
             //// 删除无效密钥
             //if (IsValidKey(rs)) RemoveKey(key);
@@ -147,7 +147,7 @@ namespace NewLife.Yun
         {
             LastResult = null;
 
-            var html = await GetStringAsync(url);
+            var html = await GetStringAsync(url).ConfigureAwait(false);
             if (html.IsNullOrEmpty()) return default(T);
 
             var rs = new JsonParser(html).Decode();
修改 +4 -4
diff --git a/XCode/Service/DbClient.cs b/XCode/Service/DbClient.cs
index 7b80329..d0086ef 100644
--- a/XCode/Service/DbClient.cs
+++ b/XCode/Service/DbClient.cs
@@ -67,7 +67,7 @@ namespace XCode.Service
             var cookie = Rand.NextString(16);
             var pass2 = cookie.GetBytes().RC4(Password.GetBytes()).ToBase64();
 
-            var rs = await InvokeWithClientAsync<LoginInfo>(client, "Db/Login", new { Db, UserName, pass = pass2, cookie });
+            var rs = await InvokeWithClientAsync<LoginInfo>(client, "Db/Login", new { Db, UserName, pass = pass2, cookie }).ConfigureAwait(false);
             if (Setting.Current.Debug) XTrace.WriteLine("登录{0}成功!{1}", Servers.FirstOrDefault(), rs.ToJson());
 
             return Info = rs;
@@ -103,7 +103,7 @@ namespace XCode.Service
         {
             var arg = Encode(sql, ps);
 
-            var rs = await InvokeAsync<Packet>("Db/Query", arg);
+            var rs = await InvokeAsync<Packet>("Db/Query", arg).ConfigureAwait(false);
             //if (rs == null || rs.Total == 0) return null;
 
             var ds = new DbTable();
@@ -120,7 +120,7 @@ namespace XCode.Service
         {
             //var arg = Encode(tableName, null);
 
-            return await InvokeAsync<Int64>("Db/QueryCount", new { tableName });
+            return await InvokeAsync<Int64>("Db/QueryCount", new { tableName }).ConfigureAwait(false);
         }
 
         /// <summary>异步执行</summary>
@@ -131,7 +131,7 @@ namespace XCode.Service
         {
             var arg = Encode(sql, ps);
 
-            return await InvokeAsync<Int64>("Db/Execute", arg);
+            return await InvokeAsync<Int64>("Db/Execute", arg).ConfigureAwait(false);
         }
         #endregion