C# 如何在短时间内发送消息

C# 如何在短时间内发送消息,c#,performance,C#,Performance,我试图在给定的时间跨度内发送大约20条消息。我想记录收到请求的时间。 现在来看下面所示的这次 var startTime = DateTime.Now; var timeoutSpan = TimeSpan.FromMilliseconds(1000); var count = 0; while ((DateTime.Now - startTime) <= timeoutSpan) {

我试图在给定的时间跨度内发送大约20条消息。我想记录收到请求的时间。 现在来看下面所示的这次

        var startTime = DateTime.Now;
        var timeoutSpan = TimeSpan.FromMilliseconds(1000);
        var count = 0;
        while ((DateTime.Now - startTime) <= timeoutSpan)
        {
            foreach (string message in messages)
            {
                txtRequest.Text = message;
                //this sends request to my service that logs a request
                sendMessageResult = client.SendMessage("Test", txtRequest.Text);
                 count++;
            }

        }
var startTime=DateTime.Now;
var timeoutSpan=TimeSpan.From毫秒(1000);
var计数=0;
而((DateTime.Now-startTime)您可以执行以下操作:

Parallel.For(0, 20, p =>
{
    var sendMessageResult = client.SendUNIMessage("Test", messages[p]);
});

如果在我的有限测试中利用TPL(客户端和服务器在同一个盒子上,客户端和服务器在GB网络连接的不同盒子上),如果我不重用wcf客户端,而是为每个线程创建一个新的客户端,我会获得更好的结果。我使用默认的VS2010 wcf应用程序模板作为x64.Net 4.0可执行文件进行了测试

我的代码如下所示:

// no multi-threading, one client
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    for (int x = 0; x < 200; x++)
    {
        wc.SendMessage("test", messages[x]);
    }
}
sw.Stop();
Console.WriteLine("plain for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// classic Threadpool 
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    var _countdown = new CountdownEvent(200);
    for (int x = 0; x < 200; x++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                // try/catch to guarantee that _countdown.Signal is always called
                try
                {
                    wc.SendMessage("Test",messages[(int) state]);
                }
                finally
                {
                    _countdown.Signal();
                }
            }, x);
    }
    _countdown.Wait();
}
sw.Stop();
Console.WriteLine("ThreadPool: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// multi-threading, one wcf client
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    Parallel.For(0, 200, x =>
        {
            wc.SendMessage("test", messages[x]);
        });
}
sw.Stop();
Console.WriteLine("tpl  paralel for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// multi-threading, client per thread
sw.Start();
int cnt = 0;
Parallel.For(
    0, 
    200, 
    () => { return new ServiceReference1.Service1Client(); },
    (x,pls,wc) =>
    {
        wc.SendMessage("test", messages[x]);
        System.Threading.Interlocked.Increment(ref cnt); // for all done check
        return wc;
    }, 
    client => {client.Close(); ((IDisposable) client).Dispose();}
);                
sw.Stop();
Console.WriteLine("tpl wc per thread paralel for: {0} ms ({1})", sw.ElapsedMilliseconds, cnt);
当在同一个盒子上运行所有内容时,平原和tpl并行之间的计时变得更加接近

请注意,由于网络和/或cpu负载的原因,时不时会出现计时跳变。我没有分析cpu或内存负载

基于此测试和设置,您可以得出结论,webclient的按线程创建是最快的


在优化性能时,请确保在目标硬件上继续测试版本,每次运行只更改一个参数/设计选项。

如果您让我们知道什么是
client.SendUNIMessage()
是。它是一个库,还是一个TCP客户端?出于性能原因,您可能应该使用来执行计时。@ErikPhilips SendMessage将请求发送到我的服务,记录请求,但如何发送?您想让我们神奇地知道它是如何工作的?它是命名为管道,还是TCP,还是UDP,还是通过SMTP发送电子邮件。我们不知道它是什么正在做。你正在尝试通过http模拟并行WCF调用吗?@cvraman我正在尝试通过http向我的服务发送给定时间内的一组消息。
// no multi-threading, one client
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    for (int x = 0; x < 200; x++)
    {
        wc.SendMessage("test", messages[x]);
    }
}
sw.Stop();
Console.WriteLine("plain for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// classic Threadpool 
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    var _countdown = new CountdownEvent(200);
    for (int x = 0; x < 200; x++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
            {
                // try/catch to guarantee that _countdown.Signal is always called
                try
                {
                    wc.SendMessage("Test",messages[(int) state]);
                }
                finally
                {
                    _countdown.Signal();
                }
            }, x);
    }
    _countdown.Wait();
}
sw.Stop();
Console.WriteLine("ThreadPool: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// multi-threading, one wcf client
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
    Parallel.For(0, 200, x =>
        {
            wc.SendMessage("test", messages[x]);
        });
}
sw.Stop();
Console.WriteLine("tpl  paralel for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

// multi-threading, client per thread
sw.Start();
int cnt = 0;
Parallel.For(
    0, 
    200, 
    () => { return new ServiceReference1.Service1Client(); },
    (x,pls,wc) =>
    {
        wc.SendMessage("test", messages[x]);
        System.Threading.Interlocked.Increment(ref cnt); // for all done check
        return wc;
    }, 
    client => {client.Close(); ((IDisposable) client).Dispose();}
);                
sw.Stop();
Console.WriteLine("tpl wc per thread paralel for: {0} ms ({1})", sw.ElapsedMilliseconds, cnt);
plain for: 769 ms
threadpool: 609 ms
tpl  paralel for: 499 ms
tpl wc per thread paralel for: 225 ms