C# ; loserInput.Text=“”; 刷新(排行榜框); } 公共类读写 { 公共静态任务AdjustStats(字符串赢家、字符串输家) { 返回任务。运行(()=> { SQLiteConnection dbConnection=newsqliteconnection(“数据源=leadboarders.sqlite;版本=3”); string sql=“从排行榜中选择*,其中name=”+winner+”; SQLiteCommand=newsqlitecommand(sql,dbConnection); dbConnection.Open(); SQLiteDataReader=await命令.ExecuteReaderAsync(); 双包装=Convert.ToDouble(读卡器[“评级”]); int wmatches=Convert.ToInt32(读卡器[“匹配]); int wwins=Convert.ToInt32(读卡器[“wins”]); sql=“从排行榜中选择*,其中名称=”+“失败者+”; command=newsqlitecommand(sql,dbConnection); reader=wait命令.ExecuteReaderAsync(); double lrating=Convert.ToDouble(读卡器[“评级”]); int lmatches=Convert.ToInt32(读卡器[“匹配]); int lwins=Convert.ToInt32(读卡器[“wins”]); int-lloss=Convert.ToInt32(读卡器[“丢失]); 双RC=(1-((包装)/200))*8; 如果(RC
问题在于您正在UI线程中运行查询。下面是一个使用C# ; loserInput.Text=“”; 刷新(排行榜框); } 公共类读写 { 公共静态任务AdjustStats(字符串赢家、字符串输家) { 返回任务。运行(()=> { SQLiteConnection dbConnection=newsqliteconnection(“数据源=leadboarders.sqlite;版本=3”); string sql=“从排行榜中选择*,其中name=”+winner+”; SQLiteCommand=newsqlitecommand(sql,dbConnection); dbConnection.Open(); SQLiteDataReader=await命令.ExecuteReaderAsync(); 双包装=Convert.ToDouble(读卡器[“评级”]); int wmatches=Convert.ToInt32(读卡器[“匹配]); int wwins=Convert.ToInt32(读卡器[“wins”]); sql=“从排行榜中选择*,其中名称=”+“失败者+”; command=newsqlitecommand(sql,dbConnection); reader=wait命令.ExecuteReaderAsync(); double lrating=Convert.ToDouble(读卡器[“评级”]); int lmatches=Convert.ToInt32(读卡器[“匹配]); int lwins=Convert.ToInt32(读卡器[“wins”]); int-lloss=Convert.ToInt32(读卡器[“丢失]); 双RC=(1-((包装)/200))*8; 如果(RC,c#,sql,database,multithreading,C#,Sql,Database,Multithreading,问题在于您正在UI线程中运行查询。下面是一个使用BackgroundWorker,的例子,它的灵感来源于和使用。这样,它将在单独的线程中运行,并且不会锁定GUI // Class for passing arguments public class BqArguments { public string Winner {get;set} public string Loser {get;set} } 以及您的实施: BackgroundWorker _bw; // You ne
BackgroundWorker
,的例子,它的灵感来源于和使用。这样,它将在单独的线程中运行,并且不会锁定GUI
// Class for passing arguments
public class BqArguments
{
public string Winner {get;set}
public string Loser {get;set}
}
以及您的实施:
BackgroundWorker _bw; // You need to initialize this somewhere.
private void adjustStatsButton_Click(object sender, EventArgs e)
{
// Maybe this should be initialized in ctor. But for this example we do it here...
_bw = new BackgroundWorker();
var arguments = new BqArguments
{
Winner = winnerInput.Text,
Loser = loserInput.Text
}
_bw.DoWork += bw_DoWork;
_bw.RunWorkerCompleted += bw_RunWorkerCompleted;
_bw.RunWorkerAsync(arguments);
}
private void bw_DoWork (object sender, DoWorkEventArgs e)
{
// Run your query in the background.
var arguments = e.Argument as BqArguments;
ReadWrite.AdjustStats(arguments.Winner, arguments.Loser);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// All done. Let's update the GUI.
winnerInput.Text = "";
loserInput.Text = "";
Refresh(leaderboardBox);
}
问题是您正在UI线程中运行查询。下面是一个使用
BackgroundWorker
,的例子,它的灵感来源于和使用。这样,它将在单独的线程中运行,并且不会锁定GUI
// Class for passing arguments
public class BqArguments
{
public string Winner {get;set}
public string Loser {get;set}
}
以及您的实施:
BackgroundWorker _bw; // You need to initialize this somewhere.
private void adjustStatsButton_Click(object sender, EventArgs e)
{
// Maybe this should be initialized in ctor. But for this example we do it here...
_bw = new BackgroundWorker();
var arguments = new BqArguments
{
Winner = winnerInput.Text,
Loser = loserInput.Text
}
_bw.DoWork += bw_DoWork;
_bw.RunWorkerCompleted += bw_RunWorkerCompleted;
_bw.RunWorkerAsync(arguments);
}
private void bw_DoWork (object sender, DoWorkEventArgs e)
{
// Run your query in the background.
var arguments = e.Argument as BqArguments;
ReadWrite.AdjustStats(arguments.Winner, arguments.Loser);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// All done. Let's update the GUI.
winnerInput.Text = "";
loserInput.Text = "";
Refresh(leaderboardBox);
}
问题的核心是在UI线程上调用阻塞(同步)数据库调用。这会在UI线程等待数据库时阻塞它,而不是让它保持良好的响应 在一般情况下,由于这些是基于I/O的操作,您应该能够使它们自然地异步,如所示。但是,SQLite不支持实际的异步操作:( 因此,在本例中,您最好将数据库工作打包到后台线程中。请注意,使用
Task.Run
远远优于BackgroundWorker
:
private async void adjustStatsButton_Click(object sender, EventArgs e)
{
await Task.Run(() => ReadWrite.AdjustStats(winnerInput.Text, loserInput.Text));
winnerInput.Text = "";
loserInput.Text = "";
Refresh(leaderboardBox);
}
问题的核心是在UI线程上调用阻塞(同步)数据库调用。这会在UI线程等待数据库时阻塞它,而不是让它保持良好的响应 在一般情况下,由于这些是基于I/O的操作,您应该能够使它们自然异步,如所示。但是,SQLite不支持实际的异步操作:( 因此,在本例中,您最好将数据库工作打包到后台线程中。请注意,使用
Task.Run
远远优于BackgroundWorker
:
private async void adjustStatsButton_Click(object sender, EventArgs e)
{
await Task.Run(() => ReadWrite.AdjustStats(winnerInput.Text, loserInput.Text));
winnerInput.Text = "";
loserInput.Text = "";
Refresh(leaderboardBox);
}
刷新什么(排行榜框)
do?旁注,注意使用参数名为winner
和loser
的sql注入。首先,您提供的代码似乎不是很重。但似乎是在GUI线程中进行的,您应该避免这样做。请尝试使用BackgroundWorker
,正如这里提到的@smoksnes谢谢,我正在做这个应用程序仅供个人使用,所以我不担心任何可能的安全问题。@Ephraimpublic static void Refresh(RichTextBox obj){obj.Text=null;ReadWrite.dbLoad(obj);obj.SelectAll();obj.SelectionAlignment=HorizontalAlignment.Center;obj.SelectionColor=Color.Black;obj.SelectionTabs=new int[]{25,20,5,5,140};}
但问题甚至在数据库更新之前就出现了,因此我认为这与此无关。刷新(排行榜框)有什么作用
do?旁注,注意使用参数名为winner
和loser
的sql注入。首先,您提供的代码似乎不是很重。但似乎是在GUI线程中进行的,您应该避免这样做。请尝试使用BackgroundWorker
,正如这里提到的@smoksnes谢谢,我正在做这个应用程序仅供个人使用,所以我不担心任何可能的安全问题。@Ephraimpublic static void Refresh(RichTextBox obj){obj.Text=null;ReadWrite.dbLoad(obj);obj.SelectAll();obj.SelectionAlignment=HorizontalAlignment.Center;obj.SelectionColor=Color.Black;obj.SelectionTabs=new int[]{25,20,5,5,140};}
但问题发生在数据库关闭之前