我的申请有点问题。 我有一个数据库编辑器,当我尝试更新数据库文件时,它有时会挂起。并非每次,但经常,并且每次在数据库发生任何更改之前发生。我认为这是因为没有使用多线程。我最近才开始学习编程,即使阅读了一些多线程解释,我也有点迷失。有人可以向我解释我应该如何在我的具体例子中实现它?
private void adjustStatsButton_Click(object sender, EventArgs e) { ReadWrite.AdjustStats(winnerInput.Text, loserInput.Text); winnerInput.Text = ""; loserInput.Text = ""; Refresh(leaderboardBox); }
public class ReadWrite
{
public static void AdjustStats(string winner, string loser)
{
SQLiteConnection dbConnection = new SQLiteConnection("Data Source = Leaderboards.sqlite; Version = 3");
string sql = "SELECT * FROM leaderboard WHERE name='" + winner + "'";
SQLiteCommand command = new SQLiteCommand(sql, dbConnection);
dbConnection.Open();
SQLiteDataReader reader = command.ExecuteReader();
double wrating = Convert.ToDouble(reader["rating"]);
int wmatches = Convert.ToInt32(reader["matches"]);
int wwins = Convert.ToInt32(reader["wins"]);
sql = "SELECT * FROM leaderboard WHERE name='" + loser + "'";
command = new SQLiteCommand(sql, dbConnection);
reader = command.ExecuteReader();
double lrating = Convert.ToDouble(reader["rating"]);
int lmatches = Convert.ToInt32(reader["matches"]);
int lwins = Convert.ToInt32(reader["wins"]);
int llosses = Convert.ToInt32(reader["losses"]);
double RC = (1 - ((wrating - lrating) / 200)) * 8;
if (RC < 0) RC *= -1;
if (RC < 4) RC = 4;
else if (RC > 12) RC = 12;
wmatches++;
wwins++;
lmatches++;
llosses++;
wrating += RC;
if (wrating < 0) wrating = 0;
lrating -= RC;
if (lrating < 0) lrating = 0;
double wwinrate = Convert.ToDouble(wwins) / wmatches;
double lwinrate = Convert.ToDouble(lwins) / lmatches;
sql = "UPDATE leaderboard SET rating=" + wrating + ", matches=" + wmatches + ", wins=" + wwins + ", winrate=" + wwinrate + " WHERE name='" + winner + "'";
command = new SQLiteCommand(sql, dbConnection);
command.ExecuteNonQuery();
sql = "UPDATE leaderboard SET rating=" + lrating + ", matches=" + lmatches + ", losses=" + llosses + ", winrate=" + lwinrate + " WHERE name='" + loser + "'";
command = new SQLiteCommand(sql, dbConnection);
command.ExecuteNonQuery();
dbConnection.Close();
}
}
答案 0 :(得分:0)
您只需要在c#代码中使用async await关键字,它最终会导致异步调用数据库我对您的代码进行了更改:
private async void adjustStatsButton_Click(object sender, EventArgs e)
{
await ReadWrite.AdjustStats(winnerInput.Text, loserInput.Text);
winnerInput.Text = "";
loserInput.Text = "";
Refresh(leaderboardBox);
}
public class ReadWrite
{
public static Task AdjustStats(string winner, string loser)
{
return Task.Run(() =>
{
SQLiteConnection dbConnection = new SQLiteConnection("Data Source = Leaderboards.sqlite; Version = 3");
string sql = "SELECT * FROM leaderboard WHERE name='" + winner + "'";
SQLiteCommand command = new SQLiteCommand(sql, dbConnection);
dbConnection.Open();
SQLiteDataReader reader = await command.ExecuteReaderAsync();
double wrating = Convert.ToDouble(reader["rating"]);
int wmatches = Convert.ToInt32(reader["matches"]);
int wwins = Convert.ToInt32(reader["wins"]);
sql = "SELECT * FROM leaderboard WHERE name='" + loser + "'";
command = new SQLiteCommand(sql, dbConnection);
reader = await command.ExecuteReaderAsync();
double lrating = Convert.ToDouble(reader["rating"]);
int lmatches = Convert.ToInt32(reader["matches"]);
int lwins = Convert.ToInt32(reader["wins"]);
int llosses = Convert.ToInt32(reader["losses"]);
double RC = (1 - ((wrating - lrating) / 200)) * 8;
if (RC < 0) RC *= -1;
if (RC < 4) RC = 4;
else if (RC > 12) RC = 12;
wmatches++;
wwins++;
lmatches++;
llosses++;
wrating += RC;
if (wrating < 0) wrating = 0;
lrating -= RC;
if (lrating < 0) lrating = 0;
double wwinrate = Convert.ToDouble(wwins) / wmatches;
double lwinrate = Convert.ToDouble(lwins) / lmatches;
sql = "UPDATE leaderboard SET rating=" + wrating + ", matches=" + wmatches + ", wins=" + wwins + ", winrate=" + wwinrate + " WHERE name='" + winner + "'";
command = new SQLiteCommand(sql, dbConnection);
await command.ExecuteNonQueryAsync();
sql = "UPDATE leaderboard SET rating=" + lrating + ", matches=" + lmatches + ", losses=" + llosses + ", winrate=" + lwinrate + " WHERE name='" + loser + "'";
command = new SQLiteCommand(sql, dbConnection);
await command.ExecuteNonQueryAsync();
dbConnection.Close();
}
});
}
答案 1 :(得分:0)
问题是您在UI线程中运行查询。以下是使用this example启发 if ($_POST["a"] != "" || $_POST["b"] != "")
{ [proceed....] }
,重度并使用Arguments
的示例。这样它将在一个单独的线程中运行,它不会锁定GUI。
BackgroundWorker
您的实施:
// Class for passing arguments
public class BqArguments
{
public string Winner {get;set}
public string Loser {get;set}
}
答案 2 :(得分:0)
您的问题的核心是您在UI线程上调用阻塞(同步)数据库调用。这会阻止你的UI线程在等待数据库时,而不是保持响应良好。
在一般情况下,由于这些是基于I / O的操作,因此应能够使它们自然地异步,如Lakhtey's answer所示。 但是,SQLite不支持实际的异步操作。 :(
因此,在这种情况下,最好的办法是将数据库工作包装到后台线程中。请注意,使用 YEAR MONTH
2012 1
2012 1
2013 10
2012 2
2014 7
远远优于if month = 1 then
date = input(compress("01/01/"||year),mmddyy10.);
else if month = 2 then
date = input(compress("02/01/"||year),mmddyy10.);
...
:
Task.Run