我有一个包含两个项目的解决方案:一个是 Web API,另一个是 Windows 窗体应用程序。在 Windows 窗体应用程序中,我发送一个获取请求来检索一些数据。所以我有这样的方法:
private async Task StartFillingEvent()
{
var path = "api/Windows/GetEventNames/";
List<EventItemDto> events = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
events = await response.Content.ReadAsAsync<List<EventItemDto>>();
var eventList = (from c in events
select new ListItemVm<Guid>()
{
Id = c.EventId,
Name = c.Title
}).ToList();
eventsDrp.FillDropDownList<Guid>("Please choose one", eventList, null);
}
}
获取我的数据并在 form_Load 中调用此方法:
private void frmOnlineBadge_Load(object sender, EventArgs e)
{
StartFillingEvent().Wait();
}
我跟踪我的应用程序,它转到 Web API 并将数据检索到 Windows 窗体应用程序。但是应用程序在 if
语句中休眠。我对多线程一无所知。我的目标是与 Web API 交互。我用谷歌搜索,发现很多教程都是关于 Windows 控制台应用程序的,而不是关于 Windows 窗体的。我用控制台应用程序检查了我的程序,但我必须使用 Forms 应用程序中的控件。
我如何管理此数据检索?
最佳答案
等待 async
方法时要小心。由于它与您执行 Wait
时在同一个线程上运行,因此您会遇到死锁。 async/await
多任务处理是协作的。这意味着 await
正在等待调用者返回控制权。如果调用者现在调用 Wait
,它将永远不会返回控制权。
解决方案是在任务中运行您的辅助方法:
private void frmOnlineBadge_Load(object sender, EventArgs e)
{
Task.Run(() => StartFillingEvent()).Wait();
}
这会将任务包装到代理中,代理将作为真正的任务运行。因此,您必须修改填充组合框的部分:
Action fillAction = delegate() {
eventsDrp.FillDropDownList<Guid>("Please choose one", eventList, null);
};
dropDownList.BeginInvoke(fillAction);
原因是因为您现在在后台运行您的操作,您必须确保在 UI 线程中执行访问 UI 的部分。这是通过 Control.BeginInvoke
完成的。
更新:
我最初写道你应该使用 Control.Invoke
。这是错误的,因为这个方法会阻塞,直到 UI 线程执行完 Action 为止。由于 UI 线程正在等待,这也会导致死锁。所以你必须使用 BeginInvoke
。
关于c# - 如何在来自 Web API 的窗体加载事件上预填充 Windows 窗体控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41101140/