【问题标题】:How to make SQlite async in UWP?如何在 UWP 中使 SQlite 异步?
【发布时间】:2017-12-18 06:23:42
【问题描述】:

我对数据库和异步编程相当陌生。我正在制作一个 POS 应用程序,它最终将拥有数百名客户和数千笔交易。当我想进行客户搜索或查找以前的工单时,我不希望我的程序挂起等待结果。

这是显示搜索结果的方法:

 private void searchCritiria_TextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
    {
        FilteredCustomer.Clear();
        if(searchCritiria.Text.Length >= 3)
        {
            SQLiteConnection dbConnection = new SQLiteConnection("Customers.db");
            string sSQL = null;

                sSQL = @"SELECT [first],[last],[spouse],[home],[work],[cell] FROM Customers";
                ISQLiteStatement dbState = dbConnection.Prepare(sSQL);

            while (dbState.Step() == SQLiteResult.ROW)
            {
                string sFirst = dbState["first"] as string;
                string sLast = dbState["last"] as string;
                string sSpouse = dbState["spouse"] as string;
                string sHome = dbState["home"] as string;
                string sWork = dbState["work"] as string;
                string sCell = dbState["cell"] as string;
                //Load into observable collection
                if (searchType.SelectedIndex == 0)//name search
                {
                    if(sFirst.Contains(searchCritiria.Text) || sLast.Contains(searchCritiria.Text) || sSpouse.Contains(searchCritiria.Text))
                    FilteredCustomer.Add(new Customer {first = sFirst, last = sLast, spouse = sSpouse, home = sHome, work = sWork, cell = sCell});
                }
                else//number search
                {
                    if(sWork.Contains(searchCritiria.Text)|| sHome.Contains(searchCritiria.Text) || sCell.Contains(searchCritiria.Text))
                    FilteredCustomer.Add(new Customer { first = sFirst, last = sLast, spouse = sSpouse, home = sHome, work = sWork, cell = sCell });
                }
            }
        }
    }

在我的整个程序中,我都有与此类似的 void 方法。

我不确定如何解决这个问题。我尝试做一些研究,但没有成功。任何建议将不胜感激!

【问题讨论】:

  • 使用await Task.Run(()=>{});,它将在异步中运行代码

标签: c# sqlite asynchronous uwp task


【解决方案1】:

编辑

正如@AndriyK 正确指出的那样,答案不会使您的代码成为asynchronous

含义: 尽管代码有效并且您可以推送数据,但如果您遇到两个线程试图写入数据库的情况(Database is Locked 条件,您的应用程序仍将冻结,直到数据库不再锁定或它超时了。这意味着任何正在运行的加载程序也会冻结。


成功了asynchronous

为此,您必须在 Task.Run() 块中运行您的 SQLite 代码。这将确保您的数据库在不同的Thread 上运行,并确保您的 UI 永远不会挂起。这也将允许您在应用程序等待数据库解锁时向用户显示ProgressRing(或其他加载程序)。下面是代码:

public void PerformSQLTasks()
{
    // your SQL code code here!  
}

并使用以下命令运行上述代码:

Task.Run(() => PerformSQLTasks());
// or even
Task.Run(PerformSQLTasks);

接受的答案:

为了让你的 UI 不挂起,你可以让你的方法返回一个 Task 而不是 void 以使其成为 awaitable。这不会使您的代码async,但会允许调用者await 这个方法完成。为此,请遵循以下方法签名:

public Task PerformSQLTasks()
{
    // your code here!  
    return Task.CompletedTask;
}

您可以通过以下方式调用它:

private async void searchCritiria_TextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
{
   await PerformSQLTasks();
}

请记住,这不会使您的代码成为Asynchronous

【讨论】:

  • 非常感谢!我刚刚编辑了代码,它编译得很好。我必须跑步,所以我回家后会测试它。如果有效,我会将其标记为正确答案。 task.completedTask 是我所缺少的。再次感谢
  • 没问题。如果您遇到任何问题,请告诉我。
  • 工作就像一个魅力!我用一个 for 循环添加了 2000 个客户,并且很快就填充了集合!
  • 仅仅改变方法返回类型不会让它异步运行。它仍然会在同一个线程中运行阻塞。
  • 完全错了。如果您 await 方法中没有异步调用,它将阻塞调用线程。 Async/await 本身并没有使应用程序成为多线程的。如果驱动程序支持异步调用,例如 MS SQL,您可以运行例如await command.ExecuterReaderAsync(),但 SQLite 驱动程序没有,所以你应该使用例如Task.Run() 手动将其踢到单独的线程中。
猜你喜欢
  • 1970-01-01
  • 2019-10-15
  • 2017-04-01
  • 2017-11-20
  • 2018-03-18
  • 1970-01-01
  • 2016-09-17
  • 2017-03-10
  • 2017-05-19
相关资源
最近更新 更多