8

我有一个小型 .Net 4.5 C# 应用程序,它从数据源读取信息,然后将此信息推送到一个网站,该网站是一个带有简单控制器的 .NET 4.5 Web API 网站。控制器接收数据并将其放入数据库。

以下对我有用,只要应用程序可以读取它可以写入并且所有内容最终都在数据库中:

    public static void PostDataToWebApi(MyDataClass tData)
    {
        HttpResponseMessage s = null;

        try
        {
            s = client.PostAsJsonAsync("/api/Station/Collector", tData).Result;
            s.EnsureSuccessStatusCode();
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR (ClientPost): " + e.ToString());
        }
    }

以下不起作用。它发布了大约一千条记录,然后出现了许多错误,所有错误都带有“任务已取消”的消息,但大约 10 秒后它恢复处理:

    public static async void PostDataToWebApi(MyDataClass tData)
    {
        HttpResponseMessage s = null;

        try
        {
            s = await client.PostAsJsonAsync("/api/Station/Collector", tData);
            s.EnsureSuccessStatusCode();
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR (ClientPost): " + e.ToString());
        }
    }

完整的错误是:

    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
    at IICE_DataCollector_Remote.Program.<PostDataToWebApi>d__7.MoveNext() in e:\Users\TestUser.TEST\Documents\Visual Studio 2012\Projects\Test_App-trunk\TestCollector\Program.cs:line 475

对此有任何快速修复吗?据我所知,它用完了一些东西,线程,套接字,谁知道:-)

任何指针都将不胜感激,我很乐意让它工作,因为您可以想象同步执行 POST 比异步执行要慢得多。

只是为了确保它不是我的机器、本地防病毒软件或网络,我在 W2k8 R2 服务器、Windows 7 虚拟访客桌面(新版本)和 Windows 8 机器上进行了尝试,结果相同。

更多信息:我已经通过具有较小数据集(10,000 条记录)和 DefaultConnectionLimit 100 的 LAN 连接进行了部分成功测试。但是,在具有 500,000 条记录的生产中,当通过 Internet 发布到远程服务器时(仍然很低延迟25ms-50ms)我没有任何成功。

提前感谢您的帮助:-)

4

1 回答 1

8

好的,我现在可以工作了。最重要的是为服务器微调客户端的设置。根据我是在本地运行测试还是通过 Internet 运行测试,这些设置会有所不同。

我的“PostDataToWebApi”方法现在看起来像这样:

    public static async void PostDataToWebApi(MyDataClass tData)
        {

        await throttler.WaitAsync();
        allTasks.Add(Task.Run(async () =>
        {

            try
            {
                var s = await client.PostAsJsonAsync("/api/Station/Collector", tData).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR (ClientPost): " + e.ToString());
            }
            finally
            {
                throttler.Release();
            }
        }));
    }

我在控制台应用程序的顶部声明了以下内容:

    private static List<Task> allTasks = new List<Task>();
    private static SemaphoreSlim throttler;

在我的循环开始之前,我有以下内容,更改了变量以确保一切正常:

    ServicePointManager.DefaultConnectionLimit = _DefaultConnections;
    ServicePointManager.MaxServicePointIdleTime = _MaxIdleTime;
    ServicePointManager.Expect100Continue = false;
    ServicePointManager.CheckCertificateRevocationList = false;

    throttle = new SemaphoreSlim(initialCount: _MaxQueue);

作为指导,对于基于 Internet 的交易,以下对我有用:

  1. 默认连接数:24
  2. 最长空闲时间:400
  3. SemaphoreSlim 初始计数:50

对于我的 LAN 测试,我可以毫无问题地同时运行默认连接和更高的初始计数值,我猜这是可以预料的 :-)

最后,就在我的外观之外,我有以下内容来确保我不会杀死在执行运行结束时仍在运行的任何任务:

     await Task.WhenAll(allTasks);

希望这可以帮助!

于 2013-08-12T02:41:13.600 回答