从静态函数调用InsertAsync会抛出ThreadAbortException
本文关键字:ThreadAbortException InsertAsync 静态 函数调用 | 更新日期: 2023-09-27 18:08:15
我希望可能有一个简单的修复,但我只是看不到它。
我试图从c#控制台程序插入数据到Azure移动服务数据库。然而,当程序从VS(通过F5)内运行时,数据没有被插入,也没有在运行程序的常规过程中抛出异常(我可以看到)。当我设置一个断点到await dataModel.InsertAsync(data)
行并在即时窗口中运行时,它会抛出一个ThreadAbortException。如有任何帮助,不胜感激。
Namespace TestApp {
class Program
{
public static MobileServiceClient MobileService = new MobileServiceClient(
"https://x.azure-mobile.net/",
"API key");
public static IMobileServiceTable<performance> dataModel = Program.MobileService.GetTable<performance>();
static void Main(string[] args)
{
try
{
var test = new performance("http://www.example.com");
var x = InsertItem(test);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
static public async Task InsertItem(performance data)
{
await dataModel.InsertAsync(data).ConfigureAwait(false);
}
}
class performance
{
[JsonProperty(PropertyName = "id")]
string Id { get; set; }
[JsonProperty(PropertyName = "uri")]
string Uri { get; set; }
public performance(string uri)
{
Uri = uri;
}
}
}
您的问题来自var x = InsertItem(test);
是非阻塞调用的事实。当你到达await dataModel.InsertAsync(data).ConfigureAwait(false);
时,函数InsertItem
立即返回Task
。
通常正确的方法是做await InsertItem(test);
,但是因为你的代码是从Main
调用的,你不能让函数async
。因此,对于这个控制台应用程序(如果在WinForms或WPF应用程序中运行,它将不是正确的选择),您需要在try-catch
块结束之前放置x.Wait()
。
static void Main(string[] args)
{
try
{
var test = new performance("http://www.example.com");
var x = InsertItem(test);
//This makes the program wait for the returned Task to complete before continuing.
x.Wait();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
然而,如果你想在WPF或WinForms应用程序中这样做,你只需要让调用函数(假设函数是一个事件)异步。
private async void Button1_OnClick(object sender, EventArgs e)
{
try
{
var test = new performance("http://www.example.com");
//The code now waits here for the function to finish.
await InsertItem(test);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
不要调用async void
函数,除非你是在一个事件委托函数
我创建了一个小测试来(某种程度上)模拟您正在做的事情。当InsertItem中等待的任务花费很少时间或根本不花费时间时,由var x = InsertItem(test)行返回的任务将返回一个处于RanToCompletion状态的任务,并且调试器将按照预期进行操作。
但是,当我让等待的任务做一些实质性的事情时,例如Thread.Sleep(5000),然后我得到您所描述的行为,var x = InsertItem(test)行返回的任务返回一个处于WaitingForActivation状态的任务。
当我把Task.WaitAll(x)后面的var x = InsertItem(test)行,然后我得到的行为,我认为我们都期望和x.状态是RanToCompletion