我有一个大型数据集来支撑我的 UI,所以我想我会创建一个后台调用来填充我的本地存储库并立即在 UI 中显示我的其他控件,并在收到响应时加载异步调用的结果。
我找到了一个有用的教程,但我仍然必须等到加载所有结果才能看到任何控件。
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
代码已更新
我创建了一个名为"服务"的文件夹,并在该文件夹中创建了"设施服务.cs,请参见下文:
public class FacilitiesService
{
internal async Task<List<Facility>> GetFacilitiesBySourceDbAsync(string sourceDb)
{
var fac = new Facility();
var con = Connect(); // Omitted
try
{
con.Open();
}
catch (Exception ex)
{
Console.WriteLine("Error: GetFacilityBySourceDb " + ex.Message);
}
try
{
OracleDataReader reader = null;
// Requestor
var cmd = new OracleCommand("SELECT FACILITY, FACILITY_ID FROM MyTable where (source_db = '" + sourceDb + "')", con);
reader = cmd.ExecuteReader();
while (reader.Read())
{
fac.Add(new Facility()
{
FacilityName = reader["FACILITY"].ToString(),
FacilityId = reader["FACILITY_ID"].ToString()
});
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
con.Dispose();
}
return fac;
}
}
然后在我的家庭控制器中.cs我有以下内容:
public class HomeController
{
public async Task<List<Facility>> FacilitiesAsync()
{
ViewBag.SyncOrAsync = "Asynchronous";
var service = new FacilitiesService();
this._facilities = new List<Facility>();
var facilities = await service.GetFacilitiesBySourceDbAsync("TEST");
foreach (var item in facilities)
{
Facility fac = new Facility()
{
FacilityName = item.FacilityName,
FacilityId = item.FacilityId
};
_facilities.Add(fac);
}
return _facilities;
}
}
这是我的设施(模型)类:
public class Facility : List<Facility>
{
[Required]
[Display(Name = "Facility")]
public string FacilityName { get; set; }
public string FacilityId { get; set; }
public Facility()
{
// Default Constructor
}
public Facility(string facilityName, string facilityId)
{
this.FacilityName = facilityName;
this.FacilityId = facilityId;
}
}
当用户使用 id 为"tags"时,我正在使用 Ajax 调用从 About.cshtml 页面中的函数调用启动代码隐藏中的 FacilityAsync 方法,我可以稍后将其切换到其他内容,但是当我单步执行代码隐藏时,我得到了数据,我看到 beforeSend 和 complete 函数都会触发警报:
<script type="text/javascript">
$(function () {
var availableTags = [
// Neeed data from function call to populate this list
];
$("#tags").autocomplete({
source: availableTags
});
$("#tags").focusout(function () {
var result = null;
$.ajax({
beforeSend: function() {
alert("Testing");
},
url: "FacilitiesAsync",
success: function(data) {
result = data;
},
complete: function () {
alert(result);
}
});
});
});
</script>
@using (Html.BeginForm()) {
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags" />
</div>
}
这很好用! 但是,我想从对代码隐藏的调用中获取数据以填充数组 availableTags,但我不确定如何做到这一点。 建议?
实现有一些问题,方法有一个问题。
首先,GetFacilitiesBySourceDbAsync
不包含await
。在这种情况下,编译器将发出警告,通知您执行此操作时它实际上不是异步方法;它将同步运行。这是一个重要的警告。如果你想要异步代码,则需要使其一直异步。这意味着使用异步数据库方法(ExecuteReaderAsync
等)。
其次,Task.WhenAll
调用Index
是没有意义的(因为你只传递了一个任务)。此外,由于Index
是同步的,但调用异步方法,因此未显示的代码可能是在调用Result
,这在 ASP.NET 上是禁忌。正如我在博客上解释的那样,一旦您的async
代码实际上是异步的,这实际上就会死锁。
但即使你修复了这些问题,它也不会做你想要的。这种方法存在一个问题,那就是async
不会更改HTTP协议(这也是指向我博客的链接)。ASP.NET MVC 了解异步方法,并且在async
操作方法完成之前不会完成请求。您需要使用 AJAX 之类的东西来让网页执行您想要的操作。