[英]Calling InsertAsync from static function throws ThreadAbortException
I expect there's probably a simple fix for this but I just can't see it. 我希望可能有一个简单的解决方法,但是我看不到。
I'm trying to insert data into an Azure Mobile Services DB from a C# Console program. 我正在尝试从C#控制台程序将数据插入到Azure移动服务数据库中。 However when the program is run from within VS (via F5), the data is not being inserted nor is an exception being thrown (that I can see) during the regular course of running the program. 但是,当从VS(通过F5)内部运行程序时,在正常运行程序期间不会插入数据,也不会抛出异常(我可以看到)。 When I set a breakpoint to the await dataModel.InsertAsync(data)
line and run that in the Immediate Window it throws a ThreadAbortException. 当我在await dataModel.InsertAsync(data)
行中设置断点并在“即时窗口”中运行该断点时,它将引发ThreadAbortException。 Any help is appreciated. 任何帮助表示赞赏。
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;
}
}
}
Your problem comes from the fact that var x = InsertItem(test);
您的问题来自以下事实: var x = InsertItem(test);
is a non blocking call. 是非阻塞呼叫。 When you get to await dataModel.InsertAsync(data).ConfigureAwait(false);
当您await dataModel.InsertAsync(data).ConfigureAwait(false);
the function InsertItem
immediately returns with a Task
. 函数InsertItem
立即返回Task
。
Normally the correct approach would be do await InsertItem(test);
通常正确的方法是await InsertItem(test);
however because your code is being called from Main
you can't make the function async
. 但是,由于您的代码是从Main
调用的,因此无法使函数async
。 So for this console application (it would not be the correct choice if running in WinForms or WPF app) You need to put a x.Wait()
before the end of your try-catch
block. 因此,对于此控制台应用程序 (如果在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);
}
}
However if you where to do this in a WPF or WinForms app you would just make the calling function (Assuming the function was a event) async. 但是,如果您要在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);
}
}
Do not do async void
function calls unless you are in a event delegate function 除非您处于事件委托函数中,否则请勿执行async void
函数调用
I created a small test to (somewhat) simulate what you're doing. 我创建了一个小测试来(某种程度上)模拟您在做什么。 When the awaited task in InsertItem takes very little or no time at all, the task returned by the var x = InsertItem(test) line returns a task in the RanToCompletion state and the debugger acts as expected. 当在InsertItem中等待的任务花费很少或根本没有时间时,由var x = InsertItem(test)行返回的任务将返回RanToCompletion状态的任务,并且调试器将按预期方式工作。
However, when I make the awaited task do something substantial, such as Thread.Sleep(5000), then I get the behavior you're describing and the task returned by the var x = InsertItem(test) line returns a task in the WaitingForActivation state. 但是,当我使等待的任务执行实质性的操作(例如Thread.Sleep(5000))时,我得到了您正在描述的行为,并且var x = InsertItem(test)行返回的任务在WaitingForActivation中返回了一个任务州。
When I put Task.WaitAll(x) following the var x = InsertItem(test) line, then I get the behavior that I think we both expect and x.Status is RanToCompletion. 当我将Task.WaitAll(x)放在var x = InsertItem(test)行之后时,我得到了我认为我们都期望的行为,而x.Status是RanToCompletion。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.