【问题标题】:Running parallel tasks c#运行并行任务 c#
【发布时间】:2016-02-28 11:48:10
【问题描述】:

在一个 Windows 商店应用程序项目中,我有一个函数,我在一个 foreach 循环中调用了多次以填充一些对象

方法头是这样的

private async Task createInvite(JsonValue item, string meetingid, List<MeetingInvitee> listInvitees)

我试图像这样在并行任务中运行它

List<Task> ts = new List<Task>();
foreach (JsonValue item in invitees)
{
    ts.Add(createInvite(item, meetingid, listInvitees));
}

await Task.WhenAll(ts);

但它似乎不会创建同时运行的任务。这大约需要 10 秒。

如果我改用这个

//List<Task> ts = new List<Task>();
foreach (JsonValue item in invitees)
{
    //ts.Add(createInvite(item, meetingid, listInvitees));
      await createInvite(item, meetingid, listInvitees);
}

//await Task.WhenAll(ts);

也需要大约 10 秒。

第一个选项我不是同时运行多个任务吗?

编辑

private async Task createInvite(JsonValue item, string meetingid, List<MeetingInvitee> listInvitees)
{
    try
    {

        Stopwatch st = Stopwatch.StartNew();
        MeetingInvitee org = new MeetingInvitee();
        MeetingInvitee altorg = new MeetingInvitee();
        JsonObject invitee2;
        JsonObject invitee;
        InviteeDB InviteeForDB = new InviteeDB();
        GappService gappservice = new GappService();

        MeetingInvitee inv = new MeetingInvitee();


        JsonObject.TryParse(item.Stringify(), out invitee2);

        invitee = invitee2["user"].GetObject();



        if (invitee2.ContainsKey("_id"))
        {
            inv.id = invitee2["_id"].GetString();
            InviteeForDB.Id = invitee2["_id"].GetString();
        }
        else
        {
            InviteeForDB.Id = invitee2["user"].GetString();
        }

        if (invitee2.ContainsKey("status"))
        {
            if (invitee2["status"].ValueType == JsonValueType.Null)
            {
                inv.status = string.Empty;
                InviteeForDB.Status = string.Empty;
            }
            else
            {
                inv.status = invitee2["status"].GetString();
                InviteeForDB.Status = invitee2["status"].GetString();
            }
        }
        Stopwatch st2 = Stopwatch.StartNew();
        if (invitee2.ContainsKey("user"))
        {

            if (invitee2["user"].ValueType != JsonValueType.Null)
            {
                User iUser = new User();
                //iUser.Id = InviteeForDB.UserID;

                JsonSerializerSettings sett = new JsonSerializerSettings();
                sett.NullValueHandling = NullValueHandling.Ignore;
                iUser = JsonConvert.DeserializeObject<User>(invitee.Stringify(), sett);

                inv.user = iUser;
            }
            else
                return;
        }
        else
            return;

        InviteeForDB.MeetingID = meetingid;
        ds.inviteeRepository.Add(InviteeForDB);
        listInvitees.Add(inv);
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.Message);
    }
}

【问题讨论】:

  • 你的代码真的是异步的吗?
  • 向我们展示您的createInvite 方法。
  • 您当前的代码正在生成一个编译器警告,准确解释您做错了什么。

标签: c# multithreading windows-runtime windows-store-apps async-await


【解决方案1】:

您的代码实际上并不是异步的(它没有 await 语句),因此所有工作都发生在 for 循环内的初始 createInvite() 调用中。

您可以使用Parallel.ForEach() 使其实际并行运行,但这会破坏您的代码,因为它实际上不是线程安全的。

【讨论】:

    【解决方案2】:

    您的方法没有真正的异步。简单地添加 async 修饰符并不会神奇地使这个异步,或者在 parallel 中执行,这是我认为你正在尝试做的。它所做的只是向编译器发出需要生成状态机的信号。这段代码将完全同步执行。

    您可以使用Task.RunParallel.ForEach 在线程池线程上显式调用您的方法,但是看看您的代码,它看起来根本就不是线程安全的。在继续之前,请尝试隔离 CreateInvite 以使其真正成为线程安全的,然后查看上述选项之一。

    【讨论】:

    • 关于如何做到这一点的任何提示?
    • 让你的代码线程安全?您可以从消除全局变量开始,并将所有内容都设置为方法调用的本地。还有read this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 2023-01-27
    • 2015-08-23
    • 2020-06-21
    相关资源
    最近更新 更多