我可以将以下内容转换为TPL代码吗?

时间:2014-07-17 10:19:41

标签: c# asynchronous task-parallel-library asyncsocket

我有以下循环通知某个事件的观察者列表:

 foreach (var observer in registeredObservers)
{
    if (observer != null)
    {
        observer.OnMessageRecieveEvent(new ObserverEvent(item));
    }
}

有没有办法可以使用TPL立即通知所有已注册的观察员?

以下是OnMessageRecieveEvent()

中执行的代码
 public void OnMessageRecieveEvent(ObserverEvent e)
    {
        SendSignal(e.message.payload);
    }

 private void SendSignal(Byte[] signal)
    {
        if (state.WorkSocket.Connected)
        {
            try
            {
                // Sends async
                state.WorkSocket.BeginSend(signal, 0, signal.Length, 0, new AsyncCallback(SendCallback), state.WorkSocket);
            }
            catch (Exception e)
            {                    
                log.Error("Transmission Failier for ip: " + state.WorkSocket.AddressFamily , e);
            }
        }
        else
        {
            CloseConnection();
        }
    }

所以我的问题是:

  1. 我该怎么做:

  2. 我真的想这样做吗?这会对表现有益吗?

3 个答案:

答案 0 :(得分:3)

由于循环的所有单次迭代都是启动异步套接字操作(这本身非常快),因此您很可能无法并行化代码。< / p>

答案 1 :(得分:1)

您的foreach循环写为Parallel.ForEach。约。

Parallel.ForEach(registeredObservers, (obs, item) =>
        {
            if (obs != null) 
               obs.OnMessageReceivedEvent(new ObserverEvent(item));
        });

答案 2 :(得分:1)

您可以尝试使用TaskCompletionSourceTask.FromAsync方法将SendSignal方法转换为Task方法。然后,您可以创建一个任务列表,并在启动所有通知后等待结果。

代码可能看起来像这样(未经测试和未编译):

public async Task NotifyObservers()
{
    List<Task> notifyTasks = new List<Task>();

    foreach (var observer in registeredObservers)
    {
        if (observer != null)
        {
            notifyTasks.Add(observer.OnMessageRecieveEvent(new ObserverEvent(item)));
        }
    }

    // asynchronously wait for all the tasks to complete
    await Task.WhenAll(notifyTasks);    
}

 public async Task OnMessageRecieveEvent(ObserverEvent e)
 {
    await SendSignal(e.message.payload);
 }

  private Task SendSignal(Byte[] signal)
  {
        if (!state.WorkSocket.Connected)
        {
            CloseConnection();
            return Task.FromResult<object>(null);
        }
        else
        {
            var tcs = new TaskCompletionSource<object>();

            try
            {
                // Sends async
                state.WorkSocket.BeginSend(signal, 0, signal.Length, 0, (ar) =>
                {
                    try
                    {
                        var socket = (Scoket)ar.AsyncState;
                        tcs.SetResult(socket.EndSend(ar));
                    }
                    catch(Exception ex)
                    {
                        tcs.SetException(ex);
                    }

                }
                , state.WorkSocket);
            }
            catch (Exception e)
            {                    
                log.Error("Transmission Failier for ip: " + state.WorkSocket.AddressFamily , e);
                tcs.SetException(e);
            }
        }

       return tcs.Task;
    }