如何在C#中正确使用异步?
我有一个来自供应商的演示应用程序。这个演示应用程序允许我通过网络连接到RFID阅读器。一旦建立了连接,我就可以扫描RFID标签,然后标签数据就会显示在应用程序上 每当CAlienServer接收到来自RFID阅读器的消息时,就会引发eventhandler如何在C#中正确使用异步?,c#,mysql,visual-studio,asynchronous,C#,Mysql,Visual Studio,Asynchronous,我有一个来自供应商的演示应用程序。这个演示应用程序允许我通过网络连接到RFID阅读器。一旦建立了连接,我就可以扫描RFID标签,然后标签数据就会显示在应用程序上 每当CAlienServer接收到来自RFID阅读器的消息时,就会引发eventhandler private void addServerEvents(int idx) { mServers[idx].ServerMessageReceived += new CAlienServer.ServerMessageReceived
private void addServerEvents(int idx)
{
mServers[idx].ServerMessageReceived += new CAlienServer.ServerMessageReceivedEventHandler(mServer_ServerMessageReceived);
mServers[idx].ServerConnectionEstablished += new CAlienServer.ServerConnectionEstablishedEventHandler(mServer_ServerConnectionEstablished);
mServers[idx].ServerConnectionEnded += new CAlienServer.ServerConnectionEndedEventHandler(mServer_ServerConnectionEnded);
mServers[idx].ServerSocketError += new CAlienServer.ServerSocketErrorEventHandler(mServer_ServerSocketError);
}
private void mServer_ServerMessageReceived(string msg)
{
if (msg != null)
{
displayText(msg.Insert(msg.IndexOf(" ") + 1, "\r\n"));
}
}
private void displayText(String data)
{
try
{
if (this.InvokeRequired)
{
object[] temp = {data};
this.Invoke(new displayMessageDlgt(displayText),temp);
return;
}
else
{
txtNotifications.Text += data.Replace("\0","") + "\r\n";
Task task = insert(data);
NotifyInfo ni = null;
AlienUtils.ParseNotification(data, out ni);
if (ni != null)
{
lblReaderName.Text = ni.ReaderName;
}
}
}
catch(Exception ex)
{
Debug.WriteLine("Exception in the DiscplayText(): " + ex.Message);
}
}
我想知道如何运行另一个函数,将变量“data”或“msg”中的数据存储到数据库中。我知道调用同步函数将不起作用,因为如果编程正在运行将数据插入数据库函数的操作,并且读取器拾取新的标记,该怎么办。因此,同步功能将不起作用。我正在考虑改用异步函数。所以我的数据库插入函数是。这是正确的方法吗
private async Task insert(string rfid)
{
await Task.Factory.StartNew(()=>
{
using (var connection = new MySqlConnection("server=localhost;user id='" + username_mysql + "';database=new;password='" + password_mysql + "'"))
{
connection.Open();
try
{
string sql = "INSERT INTO `data` (`RFID TAG`) VALUE (@rfid)";
MySqlCommand cmd = new MySqlCommand(sql, connection);
cmd.Parameters.Add("@rfid", MySqlDbType.VarChar).Value = rfid;
if (cmd.ExecuteNonQuery() == 1)
{
}
}
catch (Exception ex)
{
}
}
});
}
错误1:
更新:
代码:
服务器消息来自mServer_ServerMessageReceived(字符串消息)方法
successfull来自insert()方法
这清楚地表明所有标记数据都已插入到数据库中
调试输出:
服务器消息:00:1B:5F:00:F9:B4 0004,3,1
服务器消息:00:1B:5F:00:F9:B4 A123 0001,3,1
成功:00:1B:5F:00:F9:B4
0004,3,1
服务器消息:00:1B:5F:00:F9:B4 A641 2541,3,1
成功:00:1B:5F:00:F9:B4
A123 0001,3,1
服务器消息:00:1B:5F:00:F9:B4 0014,3,1
成功:00:1B:5F:00:F9:B4
A641 2541,3,1
服务器消息:00:1B:5F:00:F9:B4 5253 7AB2 0200 0000 0000 1002,3,1
成功:00:1B:5F:00:F9:B4
0014,3,1
服务器消息:00:1B:5F:00:F9:B4 A064 0001 0601,3,1
成功:00:1B:5F:00:F9:B4
5253 7AB2 0200 0000 0000 1002,3,1
服务器消息:00:1B:5F:00:F9:B4 0000 0000,3,1
服务器消息:00:1B:5F:00:F9:B4 0001,3,1
服务器消息:00:1B:5F:00:F9:B4 2123 6521,3,1
服务器消息:00:1B:5F:00:F9:B4 0016,3,1
成功:00:1B:5F:00:F9:B4
A064 0001 0601,3,1
成功:00:1B:5F:00:F9:B4
0000,3,1
成功:00:1B:5F:00:F9:B4
0001,3,1
成功:00:1B:5F:00:F9:B4
21236521,3,1
成功:00:1B:5F:00:F9:B4
0016,3,1您可能应该改用。请注意,这可能会也可能不会实际执行异步
对于Oracles MySql连接器,所有异步方法。声称提供真正的异步支持,但我还没有对此进行测试。(感谢布拉德利·格兰杰提供更多信息。)
如果您确定查询实际上是同步运行的,那么在后台线程上运行查询可能是合理的,以避免阻塞UI(如果是UI应用程序)。如果是这样的话,那么最好先创建一个同步方法
private void insert(string rfid){
...
}
然后像这样称呼它
private async Task displayText(String data){
....
await Task.Run(() => insert(rfid));
...
}
如果这样做,则需要确保该方法是线程安全的。如果不能保证这一点,则不应在其他线程上运行它。请注意,您应该确保正确处理异常。即
- 避免空捕获,所有异常都应该以某种方式处理。如果无法插入所需的数据,则可能会通知用户
- 应等待所有任务,否则将丢失任何异常
- 避免使用
,因为这使得调用者无法等待,因此无法接收任何异常async void
- 对于事件处理程序(即按下按钮),您需要使用
,在这种情况下,您应该确保捕获任何异常并采取适当的操作。可能会通知用户故障,和/或终止应用程序async void
async
无关。删除Task.Factory.StartNew
。将cmd.ExecuteNonQuery
更改为wait cmd.executenonquerysync
。如果你有一个实际的并发问题,发布一个不同的问题并包括详细信息。根据C#中的方法名称,请遵循PascalCase模式。异步方法也应该有后缀。因此,它是InsertAsync
,而不是insert
@Paul实现您的代码并进行测试,看看您是否可以重现您提到的那种问题(“将数据插入数据库函数,然后读取器拾取新标记”),将displayText()设置为异步方法与insert()之间有什么区别请注意,对于MySql.Data,所有“异步”方法实际上都是同步执行的:在.NET中使用MySql实现真正异步I/O的唯一方法是切换到不同的ADO.NET库:@Paul,无论何时调用异步方法,都需要处理结果,即使这只是一个执行选项,也可以通过等待来轻松完成。因此,调用方还需要是异步任务
。这将一直持续到您可以适当处理异常的程度,可能是在UI层。@Bradley Grainger感谢您提供的信息,并将其添加到了答案中。我也这么怀疑,但没有参考资料。@Paul有很多指南和最佳实践描述了如何处理异常。也许是个好的开始。
private async Task displayText(String data){
....
await Task.Run(() => insert(rfid));
...
}