小编dar*_*key的帖子

任务继续与async/await并行执行

在使用async/await结构的控制台应用程序的上下文中,我想知道"continuation"是否可以在不同CPU上的多个线程上并行运行.

我认为就是这种情况,因为延迟发布在默认任务调度程序(控制台应用程序中没有SynchronizationContext)上,这是线程池.

我知道async/await构造不构造任何额外的线程.仍然应该由线程池为每个CPU构建至少一个线程,因此如果在线程池上发布了continuation,它可以在不同的CPU上并行调度任务延续...这就是我的想法,但出于某种原因我昨天对此我真的很困惑,我不再那么肯定了.

这是一些简单的代码:

public class AsyncTest
{
  int i;

  public async Task DoOpAsync()
  {
    await SomeOperationAsync();

    // Does the following code continuation can run 
    // in parrallel ?
    i++;       

    // some other continuation code ....
  }

  public void Start()
  {
    for (int i=0; i<1000; i++)
    { var _ = DoOpAsync(); } // dummy variable to bypass warning
  }
}
Run Code Online (Sandbox Code Playgroud)

SomeOperationAsync本身不会创建任何线程,让我们假设为了示例它只是依赖I/O完成端口异步发送一些请求,因此根本不会阻塞任何线程.

现在,如果我调用将发出1000个异步操作的Start方法,是否可以在不同的CPU线程上并行运行async方法的延续代码(在await之后)?即在这种情况下我是否需要处理线程同步并同步对字段"i"的访问?

c# multithreading threadpool task-parallel-library async-await

7
推荐指数
2
解决办法
903
查看次数

NLog File目标和keepFileOpen标志

NLog中的FileTarget对象具有名为"keepFileOpen"的属性(bool).默认情况下,此属性设置为false,这意味着每个日志事件将打开文件,写入文件并关闭文件.

性能上的打击是巨大的,所以我将"keepFileOpen"指定为true而不是false,这意味着该文件只会打开一次.

是否有人有想法(或只知道)为什么默认情况下将此属性设置为"false",从而在日志记录中产生巨大的性能损失?

是否存在将此属性设置为true的情况会导致问题(因此将其默认为"false"是有意义的).

谢谢 !

编辑

基本布局的性能测量,将100K事件写入记录器:

  • keepFileOpen = false(默认值):~101秒
  • keepFileOpen = true:~1秒

c# nlog

6
推荐指数
2
解决办法
2266
查看次数

调用异步方法vs事件

我正在为网络应用程序协议开发客户端库.

客户端代码调用库来初始化它并连接到服务器.客户端当然可以向服务器发送请求,但服务器也可以向客户端发送请求(命令,下面称为Cmd).

传输协议是TCP/IP,因此基本上客户端库连接到服务器并调用异步方法以从服务器检索下一个请求或响应,以避免在等待响应/请求时阻止I/O服务器.

话虽这么说,我在库中看到两种可能的解决方案(仅使用C#构造,没有特定的第三方框架),以允许客户端从服务器接收请求:

要么在图书馆提供活动,如

public EventHandler<ReceivedCmdEventArgs> event ReceivedCmd;
Run Code Online (Sandbox Code Playgroud)

客户端将订阅,以便了解从服务器传入的请求.当然对于这种机制,我将不得不在客户端库中创建一个异步循环来接收来自服务器的请求并在Cmd接收时引发事件.

或者另一种解决方案是在客户端库中创建这样的方法

public async Task<Cmd> GetNextCmdAsync()
Run Code Online (Sandbox Code Playgroud)

客户端代码将在异步循环中调用以接收cmds.

这些解决方案有点相同吗?是否更好地完全使用C#5的async/await constrcuts而不再依赖于事件?有什么区别 ?任何建议,评论?

谢谢 !

c# events async-await

6
推荐指数
1
解决办法
3066
查看次数

需要一个更好的"回调调度程序"组件设计

从客户端应用程序我发送请求/事务(包含执行(和参数)+ transactionID的操作)到远程队列.远程服务器在某个时候将请求出列,并且需要一些时间来处理它.

一旦完成处理它,它就会在客户端队列上发送一个响应(包含应用响应+ transactionID)...所以这是一个完全"断开连接"的通信模式,客户端可以将响应映射到请求是通过transactionID.

消息响应在客户端出列,并与原始请求匹配(基于transactionID).

我现在正在做的是,当客户端将请求发布到服务器队列时,它会向保留transactionId和callback(委托)的字典添加回调.这是一个Dictionary<int, object>将transactionId映射回回调用操作结果调用的回调.

回调/委托存储为对象,因为根据请求,回调委托签名是不同的(例如,响应可以返回a List<string>而另一个响应可以返回int).

当客户端队列使响应出列时,它知道响应的类型(因此知道回调的相应签名),因此它根据transactionID从字典中获取回调.然后它将对象强制转换回相应的委托类型并调用回调.

我发现这种方法不是很"性感",但我并没有真正看到另一种方法来执行这样的任务.

有没有更好的方法来执行此操作?

如果问题不够明确,请告诉我并通过一些编辑进行澄清.

c# algorithm

5
推荐指数
1
解决办法
145
查看次数

异步方法在桌面上没有阻塞但在服务器上阻塞?

我做了一个简单的异步方法来异步调用SQL存储过程.

在我的控制台程序中,我在循环中调用此方法1000次,并在每次调用之间休眠1ms(Thread.Sleep).我在进入循环之前启动一个StopWatch,并在退出循环时停止它,并显示在循环中花费的时间.

在我的开发机器(Win7 - VS 2012 RC)上,我可以看到我期待看到的内容:

Completed in 1006 ms
Run Code Online (Sandbox Code Playgroud)

考虑到异步方法的调用几乎立即返回(当到达第一个await关键字时),这似乎是合乎逻辑的,因此在等待之前执行代码时只需要很小的开销(6ms).

但是,当我在已安装.NET Framework 4.5 RC的服务器计算机(Win2008 R2 SP1)上运行完全相同的代码时,代码运行正常但是执行时间远远不是我期望的那样,与在我的开发机器上运行程序时获得的一个:

Completed in 15520 ms
Run Code Online (Sandbox Code Playgroud)

意味着以某种方式调用异步方法并不是真的异步调用,第一个await似乎以某种方式阻塞?

这是我调用的异步方法的代码:

public async void CallSpAsync()
{
  var cmd = new SqlCommand("sp_mysp");
  {  
     var conn = new SqlConnection(connectionString);
     {
       cmd.Connection = conn;
       cmd.CommandType = CommandType.StoredProcedure;

       [...Filling command parameters here - nothing interesting...]

       await cmd.Connection.OpenAsync();                    
       await cmd.ExecuteNonQueryAsync();

       cmd.Dispose();
       cmd.Connection.Dispose();
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

这是主程序测试代码(循环):

Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; …
Run Code Online (Sandbox Code Playgroud)

.net c# async-await

5
推荐指数
1
解决办法
354
查看次数

跨AppDomain异步方法调用

从主AppDomain,我试图调用以不同AppDomain中实例化的类型定义的异步方法。

例如,以下类型MyClass继承MarshalByRefObject自新AppDomain并在其中实例化:

public class MyClass : MarshalByRefObject
{
  public async Task<string> FooAsync()
  {
     await Task.Delay(1000);
     return "Foo";
  }
}
Run Code Online (Sandbox Code Playgroud)

在主AppDomain中,我创建一个新的AppDomain并在此AppDomain中创建MyClass的实例,然后调用异步方法。

var appDomain = AppDomain.CreateDomain("MyDomain");
var myClass = (MyClass)appDomain.CreateInstanceAndUnwrap(typeof(MyClass).Assembly.FullName, typeof(MyClass).FullName);
await myClass.FooAsync(); // BAM !
Run Code Online (Sandbox Code Playgroud)

当然,SerializationException当我尝试进行调用时会收到一个,因为该Task类型不继承自MarshalByRefObject,也不可序列化。

我怎样才能解决这个问题?我真的很希望能够从另一个AppDomain中实例化的类型上调用/等待异步方法...有没有办法?

谢谢 !

c# appdomain async-await

5
推荐指数
1
解决办法
2255
查看次数

System.Messaging - 为什么MessageQueue不提供异步版本的Send

有谁知道为什么System.Messaging没有提供Send方法的异步版本来向队列发送MSMQ消息.

实际上有Peek和Receive方法的异步版本(通过Begin/End对可以转换为C#5 async awaitable方法),但是很明显没有提供BeginSend/EndSend方法,只是一个发送方法,在我看来像这是一个同步阻塞I/O调用.

我认为这不是System.Messaging的限制,而是System.Messaging正在使用的本机消息队列API(mqrt.dll)之一,它将重叠结构作为函数中的参数MQReceiveMessage使用与IOCP重叠I/O,虽然函数MQsendMessage不采用这种结构,所以看起来它是纯粹的同步调用.

我的问题仍然存在,任何人都会知道为什么MessageQueue API不提供将消息发送到队列的异步方式?

c# msmq async-await

5
推荐指数
1
解决办法
888
查看次数

等待并返回呼叫者

如果我有一个异步方法:

public async Task MyMethodAsync()
{
   // [.. Some synchronous code here ..]

   await AnotherAsyncMethod();
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中的某些时候,我称之为:

await MyMethodAsync();
Run Code Online (Sandbox Code Playgroud)

即使输入MyMehodAsync,此语句是否会立即返回给调用者?我想是的但不确定.

如果我希望调用MyMethodAsync首先[.. Some synchronous code here ..]立即执行该部分,我应该更喜欢:

var t = MyMethodAsync(); 
await t;                 
Run Code Online (Sandbox Code Playgroud)

谢谢

c# async-await

3
推荐指数
1
解决办法
698
查看次数