C#如何捕获异步结果?
C# how to capture async results?
我是 C# 的新手,我正在尝试使用 Lync SDK 以编程方式搜索 Lync 用户以获取他们的状态。我不确定在执行异步回调时如何将结果传递给 web 服务响应。
这是代码:
Web 服务控制器 GET 端点:
// GET: api/Lync/5
public String Get(int id)
{
log.Info("[GET] Search for Lync User: " + id);
Lync lync = new Lync();
////lync.signIn();
Boolean isSignedIn = lync.isUserSignedIn();
if (isSignedIn)
{
log.Info("User is Signed In");
Console.Write("Enter search key : ");
lync.Search("medina");
//lync.Search("medina",
//(lyncContacts) =>
//{
// log.Debug("Search Results Callback fired!");
// log.Info("Results found: " + lyncContacts.Count);
// return lyncContacts.ToString();
//});
//Console.WriteLine(name);
//Console.ReadLine();
return "testUser";
}
else
{
log.Info("User is not Signed In!");
// TODO: Return status 500
return "testUser";
}
//Console.ReadLine();
//return "testUser";
}
上述方法调用业务服务lync.search(..)如下:
public void Search(string searchKey)
{
List<LyncContact> contactList = new List<LyncContact>();
//List<ContactInformationType> ContactInformationList = new List<ContactInformationType>();
//ContactInformationList.Add(ContactInformationType.Activity);
//ContactInformationList.Add(ContactInformationType.Availability);
// ContactInformationList.Add(ContactInformationType.CapabilityString);
//ContactSubscription contactSubscription = LyncClient.GetClient().ContactManager.CreateSubscription();
Console.WriteLine("Searching for contacts on " + searchKey);
LyncClient.GetClient().ContactManager.BeginSearch(
searchKey,
(ar) =>
{
SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar);
if (searchResults.Contacts.Count > 0)
{
log.Info("Search results found: " + searchResults.Contacts.Count);
Console.WriteLine(searchResults.Contacts.Count.ToString() + " found");
foreach (Contact contact in searchResults.Contacts)
{
String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString();
ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability);
Console.WriteLine(
contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString());
log.Debug("Display Name: " + displayName);
log.Debug("Availability: " + currentAvailability);
LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build();
contactList.Add(lyncContact);
//done(contactList);
}
return;
}
else
{
log.Info("No Results found!");
//done(contactList);
return;
}
},
null);
} else
{
log.Info("No Results found!");
//done(contactList);
return;
}
},
null);
}
我尝试使用 Task+await,但我很难弄清楚如何才能 return 将回调函数的结果作为搜索方法的结果。我如何在控制器中捕获它 class?
通过查看您注释掉的代码,您似乎试图为 Search
函数提供某种回调。那行得通,它应该是 Action<Microsoft.Lync.Model.SearchResults>
类型
public void Search(string searchKey, Action<SearchResults> callback)
{
....
LyncClient.GetClient().ContactManager.BeginSearch(
searchKey,
(ar) =>
{
SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar);
callback(searchResults);
});
....
}
然后取消注释控制器中的代码:
lync.Search("medina",
(lyncContacts) =>
{
log.Debug("Search Results Callback fired!");
log.Info("Results found: " + lyncContacts.AllResults.Count);
});
如果您想为此使用 async/await 模式 Task.FromAsync
https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync(v=vs.110).aspx
Google 例如。像这样:
public async Task<List<LyncContact>> SearchAsync(string searchKey)
{
List<LyncContact> contactList = new List<LyncContact>();
Console.WriteLine("Searching for contacts on " + searchKey);
var cm = LyncClient.GetClient().ContactManager;
var searchResults = await Task<SearchResults>.Factory.FromAsync<String>(
cm.BeginSearch,
cm.EndSearch, searchKey, null);
if (searchResults.Contacts.Count > 0)
{
Console.WriteLine(searchResults.Contacts.Count.ToString() + " found");
foreach (Contact contact in searchResults.Contacts)
{
String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString();
ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability);
Console.WriteLine(
contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString());
LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build();
contactList.Add(lyncContact);
}
}
return contactList
}
然后在控制器中你可以做:
public async Task<String> Get(int id)
{
log.Info("[GET] Search for Lync User: " + id);
Lync lync = new Lync();
////lync.signIn();
Boolean isSignedIn = lync.isUserSignedIn();
if (isSignedIn)
{
log.Info("User is Signed In");
Console.Write("Enter search key : ");
var lyncContacts = await SearchAsync("medina");
log.Info("Results found: " + lyncContacts.Count);
return lyncContacts.ToString();
}
else
{
log.Info("User is not Signed In!");
// TODO: Return status 500
return "testUser";
}
//Console.ReadLine();
//return "testUser";
}
或者您可以使用 TaskCompletionSource
,参见 http://blog.stephencleary.com/2012/07/async-interop-with-iasyncresult.html(较旧的 post 但原则仍然有效。
警告
我无法编译它,因为我无权访问您使用的库。它应该可以工作,但可能存在一些编译错误
它有什么作用
如您所知,回调不是一个很好的模型。使用任务和 async/await 模型更容易使用。对你我来说幸运的是,他们创造了几种方法,可以充当新旧模型之间的桥梁。使用 Task.FromAsync 您可以将 IAsyncResult 方法转换为更易于使用的基于任务的方法。 Stephen Cleary 写了一些关于它们的不错的博客。参见我前面提到的post。
我是 C# 的新手,我正在尝试使用 Lync SDK 以编程方式搜索 Lync 用户以获取他们的状态。我不确定在执行异步回调时如何将结果传递给 web 服务响应。
这是代码:
Web 服务控制器 GET 端点:
// GET: api/Lync/5
public String Get(int id)
{
log.Info("[GET] Search for Lync User: " + id);
Lync lync = new Lync();
////lync.signIn();
Boolean isSignedIn = lync.isUserSignedIn();
if (isSignedIn)
{
log.Info("User is Signed In");
Console.Write("Enter search key : ");
lync.Search("medina");
//lync.Search("medina",
//(lyncContacts) =>
//{
// log.Debug("Search Results Callback fired!");
// log.Info("Results found: " + lyncContacts.Count);
// return lyncContacts.ToString();
//});
//Console.WriteLine(name);
//Console.ReadLine();
return "testUser";
}
else
{
log.Info("User is not Signed In!");
// TODO: Return status 500
return "testUser";
}
//Console.ReadLine();
//return "testUser";
}
上述方法调用业务服务lync.search(..)如下:
public void Search(string searchKey)
{
List<LyncContact> contactList = new List<LyncContact>();
//List<ContactInformationType> ContactInformationList = new List<ContactInformationType>();
//ContactInformationList.Add(ContactInformationType.Activity);
//ContactInformationList.Add(ContactInformationType.Availability);
// ContactInformationList.Add(ContactInformationType.CapabilityString);
//ContactSubscription contactSubscription = LyncClient.GetClient().ContactManager.CreateSubscription();
Console.WriteLine("Searching for contacts on " + searchKey);
LyncClient.GetClient().ContactManager.BeginSearch(
searchKey,
(ar) =>
{
SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar);
if (searchResults.Contacts.Count > 0)
{
log.Info("Search results found: " + searchResults.Contacts.Count);
Console.WriteLine(searchResults.Contacts.Count.ToString() + " found");
foreach (Contact contact in searchResults.Contacts)
{
String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString();
ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability);
Console.WriteLine(
contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString());
log.Debug("Display Name: " + displayName);
log.Debug("Availability: " + currentAvailability);
LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build();
contactList.Add(lyncContact);
//done(contactList);
}
return;
}
else
{
log.Info("No Results found!");
//done(contactList);
return;
}
},
null);
} else
{
log.Info("No Results found!");
//done(contactList);
return;
}
},
null);
}
我尝试使用 Task+await,但我很难弄清楚如何才能 return 将回调函数的结果作为搜索方法的结果。我如何在控制器中捕获它 class?
通过查看您注释掉的代码,您似乎试图为 Search
函数提供某种回调。那行得通,它应该是 Action<Microsoft.Lync.Model.SearchResults>
public void Search(string searchKey, Action<SearchResults> callback)
{
....
LyncClient.GetClient().ContactManager.BeginSearch(
searchKey,
(ar) =>
{
SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar);
callback(searchResults);
});
....
}
然后取消注释控制器中的代码:
lync.Search("medina",
(lyncContacts) =>
{
log.Debug("Search Results Callback fired!");
log.Info("Results found: " + lyncContacts.AllResults.Count);
});
如果您想为此使用 async/await 模式 Task.FromAsync
https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync(v=vs.110).aspx
Google 例如。像这样:
public async Task<List<LyncContact>> SearchAsync(string searchKey)
{
List<LyncContact> contactList = new List<LyncContact>();
Console.WriteLine("Searching for contacts on " + searchKey);
var cm = LyncClient.GetClient().ContactManager;
var searchResults = await Task<SearchResults>.Factory.FromAsync<String>(
cm.BeginSearch,
cm.EndSearch, searchKey, null);
if (searchResults.Contacts.Count > 0)
{
Console.WriteLine(searchResults.Contacts.Count.ToString() + " found");
foreach (Contact contact in searchResults.Contacts)
{
String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString();
ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability);
Console.WriteLine(
contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString());
LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build();
contactList.Add(lyncContact);
}
}
return contactList
}
然后在控制器中你可以做:
public async Task<String> Get(int id)
{
log.Info("[GET] Search for Lync User: " + id);
Lync lync = new Lync();
////lync.signIn();
Boolean isSignedIn = lync.isUserSignedIn();
if (isSignedIn)
{
log.Info("User is Signed In");
Console.Write("Enter search key : ");
var lyncContacts = await SearchAsync("medina");
log.Info("Results found: " + lyncContacts.Count);
return lyncContacts.ToString();
}
else
{
log.Info("User is not Signed In!");
// TODO: Return status 500
return "testUser";
}
//Console.ReadLine();
//return "testUser";
}
或者您可以使用 TaskCompletionSource
,参见 http://blog.stephencleary.com/2012/07/async-interop-with-iasyncresult.html(较旧的 post 但原则仍然有效。
警告
我无法编译它,因为我无权访问您使用的库。它应该可以工作,但可能存在一些编译错误
它有什么作用
如您所知,回调不是一个很好的模型。使用任务和 async/await 模型更容易使用。对你我来说幸运的是,他们创造了几种方法,可以充当新旧模型之间的桥梁。使用 Task.FromAsync 您可以将 IAsyncResult 方法转换为更易于使用的基于任务的方法。 Stephen Cleary 写了一些关于它们的不错的博客。参见我前面提到的post。