C# Winform-将方法更改为异步/等待

C# Winform-将方法更改为异步/等待,c#,multithreading,winforms,async-await,C#,Multithreading,Winforms,Async Await,我有一个winform和六个listbox并排。在每个列表框下都有一个文本框和一个标记为“添加”的按钮。当您在文本框中放入内容并按下添加按钮时,使用EF,我会更新该列表框的表格,并重新对列表框进行数据绑定。下面是Add按钮的一个事件处理程序示例: private void btnOfferType_Click(object sender, EventArgs e) { TypeCategoryAdd("OfferType", tbOfferType.Text.Trim()); } Ty

我有一个
winform
和六个
listbox
并排。在每个
列表框
下都有一个
文本框
和一个标记为“添加”的
按钮
。当您在
文本框
中放入内容并按下添加按钮时,使用EF,我会更新该
列表框
的表格,并重新对
列表框
进行数据绑定。下面是Add按钮的一个事件处理程序示例:

private void btnOfferType_Click(object sender, EventArgs e)
{
    TypeCategoryAdd("OfferType", tbOfferType.Text.Trim());
}
TypeCategoryAdd
函数如下所示。我想这样做(注意
wait
):

我需要做什么才能使
TypeCategoryAdd
函数在不同的上下文上运行,以便
winform
UI在数据库更新时不会冻结

private void TypeCategoryAdd (string table, string item)
{
    if (string.IsNullOrEmpty(item)) return;

    using (MenuGenerator.NewArchMenuGeneratorEntities con = new NewArchMenuGeneratorEntities())
    {
        switch (table)
        {
            case "OfferType":
                if (con.OfferTypes.Any(x=>x.Name == item))
                {
                    MessageBox.Show("There is already a " + item + " on the list!");
                    tbOfferType.Text = "";
                    return;
                }
                OfferType ot = new OfferType();
                ot.Name = item;
                con.OfferTypes.Add(ot);
                try
                {
                    con.SaveChanges();
                    tbOfferType.Text = "";
                    lstOfferType.DataSource = con.OfferTypes.OrderBy(x=>x.Id).ToList();                    
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error " + ex.ToString());
                }
                break;                

            }
            return;
        }

如何利用EF 6中的
async
方法:

private async Task TypeCategoryAdd (string table, string item)
{
    if (string.IsNullOrEmpty(item)) return;

    using (MenuGenerator.NewArchMenuGeneratorEntities con = new NewArchMenuGeneratorEntities())
    {
        switch (table)
        {
            case "OfferType":
                if (await con.OfferTypes.AnyAsync(x=>x.Name == item))
                {
                    MessageBox.Show("There is already a " + item + " on the list!");
                    tbOfferType.Text = "";
                    return;
                }
                OfferType ot = new OfferType();
                ot.Name = item;
                con.OfferTypes.Add(ot);
                try
                {
                    await con.SaveChangesAsync();
                    tbOfferType.Text = "";
                    lstOfferType.DataSource = await con.OfferTypes.OrderBy(x=>x.Id).ToListAsync();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error " + ex.ToString());
                }
                break;                

            }
            return;
        }
    }
}

如何利用EF 6中的
async
方法:

private async Task TypeCategoryAdd (string table, string item)
{
    if (string.IsNullOrEmpty(item)) return;

    using (MenuGenerator.NewArchMenuGeneratorEntities con = new NewArchMenuGeneratorEntities())
    {
        switch (table)
        {
            case "OfferType":
                if (await con.OfferTypes.AnyAsync(x=>x.Name == item))
                {
                    MessageBox.Show("There is already a " + item + " on the list!");
                    tbOfferType.Text = "";
                    return;
                }
                OfferType ot = new OfferType();
                ot.Name = item;
                con.OfferTypes.Add(ot);
                try
                {
                    await con.SaveChangesAsync();
                    tbOfferType.Text = "";
                    lstOfferType.DataSource = await con.OfferTypes.OrderBy(x=>x.Id).ToListAsync();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error " + ex.ToString());
                }
                break;                

            }
            return;
        }
    }
}

您可以将数据库访问权包装在
任务中
,然后等待该任务

private async void btnOfferType_Click(object sender, EventArgs e)
{
    await Task.Run(()=>TypeCategoryAdd("OfferType", tbOfferType.Text.Trim()));
}

您可以将数据库访问权包装在
任务中
,然后等待该任务

private async void btnOfferType_Click(object sender, EventArgs e)
{
    await Task.Run(()=>TypeCategoryAdd("OfferType", tbOfferType.Text.Trim()));
}

请将代码缩减为@StephenCleary Done。将代码减少为一个
案例
。谢谢你的帮助、精彩的文章、你的博客和你的书。@StephenCleary一些拥有3K代表积分的人试图帮助我,但他尝试的任何东西都会产生某种错误。因此,他决定删除整个答案。我又回到原点了。如果您对我的问题有任何建议,我将不胜感激。我发布的链接描述了一个最小的、完整的、可验证的示例。这就是你需要的。就目前情况而言,它还不完整(即,我无法将其复制到新项目中并查看您看到的内容)。请将代码简化为。@stephenleary Done。将代码减少为一个
案例
。谢谢你的帮助、精彩的文章、你的博客和你的书。@StephenCleary一些拥有3K代表积分的人试图帮助我,但他尝试的任何东西都会产生某种错误。因此,他决定删除整个答案。我又回到原点了。如果您对我的问题有任何建议,我将不胜感激。我发布的链接描述了一个最小的、完整的、可验证的示例。这就是你需要的。目前,它还不完整(也就是说,我无法将它复制到新项目中并查看您看到的内容)。我使用的是ADO.Net实体框架。遗憾的是,它没有附带
savechangessync
@Zuzlx如果您使用的是旧版本,您不能升级吗?看来我除了升级别无选择。否则,(这里可能我错了)我们必须在
Task
中包装东西,这样我们才能将
可等待的对象返回给调用者。我使用的是ADO.Net实体框架。遗憾的是,它没有附带
savechangessync
@Zuzlx如果您使用的是旧版本,您不能升级吗?看来我除了升级别无选择。否则,(这里可能我错了)我们必须在
Task
中包装东西,这样我们才能将
等待的对象返回给调用方。