等待通知的异步调用

4
我将尝试获取给定用户的lync在线状态。我的代码将使用UCMA 4.0在64位环境下与lync服务器2010通信。
以下是我的代码,用于等待异步调用以获取lync状态。
private async void getNotifications(UserEndpoint endpoint, string useridSIP)
{
    _userEndpoint.PresenceServices.BeginPresenceQuery(
        new[] { useridSIP },
        new[] { "state" },
        null,
        (ar) => {
            Task<List<RemotePresentityNotification>> notificationFetch = _userEndpoint.PresenceServices.EndPresenceQuery(ar).ToList<RemotePresentityNotification>();
            List<RemotePresentityNotification> result = await notificationFetch;
            result.ForEach(x => {
                LyncUser user = new LyncUser();
                if (x.AggregatedPresenceState != null)
                {
                    user.Presence = x.AggregatedPresenceState.Availability.ToString();
                }
                else
                {
                    user.Presence = "Unknown";
                }
                user.UserName = x.PresentityUri.ToString();
                usersWithStatus.Add(user);
            });
        },
        null);
}

我不确定如何等待List<RemotePresentityNotification>结果返回

Task<List<RemotePresentityNotification>> notificationFetch = _userEndpoint.PresenceServices.EndPresenceQuery(ar).ToList<RemotePresentityNotification>();
List<RemotePresentityNotification> result = await notificationFetch;

整个源代码。
using Microsoft.Rtc.Collaboration;
using Microsoft.Rtc.Collaboration.Presence;
using Oobe.Bobs.Lync.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace xxxx.xxxx.xxxx
{
    public class OneTimePresence
    {
        private UCMASampleHelper _helper;
        private UserEndpoint _userEndpoint;
        public List<LyncUser> usersWithStatus = new List<LyncUser>();
        public LyncPresenceChecker _checker { get; set; }
        public OneTimePresence(string useridSIP, LyncPresenceChecker checker)
        {
            _checker = checker;
            _helper = new UCMASampleHelper();
            string endpoint = String.Format("OneTime Presence query for {0}", useridSIP);
            _userEndpoint = _helper.CreateEstablishedUserEndpoint(endpoint);
            getNotifications(_userEndpoint, useridSIP);
            _helper.ShutdownPlatform();

        }
        protected void EndgetNotification(object sender, RemotePresentitiesNotificationEventArgs e)
        {
            e.Notifications.ToList<RemotePresentityNotification>().ForEach(x =>
            {
                LyncUser user = new LyncUser();
                if (x.AggregatedPresenceState != null)
                {
                    user.Presence = x.AggregatedPresenceState.Availability.ToString();
                }
                else
                {
                    user.Presence = "Unknown";
                }
                user.UserName = x.PresentityUri.ToString();
                usersWithStatus.Add(user);
            });
            _checker.Clients.All.updateLyncUserPresence(usersWithStatus);

        }

        private void getNotifications(UserEndpoint endpoint, string useridSIP)
        {
            _userEndpoint.PresenceServices.BeginPresenceQuery(
                new[] { useridSIP },
                new[] { "state" },
                EndgetNotification,
                (ar) => {
                    ar.AsyncWaitHandle.WaitOne();
                    List<RemotePresentityNotification> result = _userEndpoint.PresenceServices.EndPresenceQuery(ar).ToList<RemotePresentityNotification>();

                    result.ForEach(x =>
                    {
                        LyncUser user = new LyncUser();
                        if (x.AggregatedPresenceState != null)
                        {
                            user.Presence = x.AggregatedPresenceState.Availability.ToString();
                        }
                        else
                        {
                            user.Presence = "Unknown";
                        }
                        user.UserName = x.PresentityUri.ToString();
                        usersWithStatus.Add(user);
                    });
                },
                null);
            if (usersWithStatus.Count > 0)
            {
                _checker.Clients.All.updateLyncUserPresence(usersWithStatus);
            }

        }


    }
}

不要使用async void。请参阅此文章以获取完整说明。将getNotifications的方法签名更改为async Task。为什么要等待结果? - Jeroen Heier
Lync服务器需要一些时间才能返回状态,因此会异步调用匿名方法。 - Vinay Joseph
1个回答

2
我相信您正在寻找 Task.Factory.FromAsync 方法。该方法是对 BeginEnd async 模式的封装 -- 具体内容请参考 此处。例如,您应该这样做:
private async Task<List<RemotePresentityNotification>> GetNotifications(UserEndpoint endpoint, string useridSIP)
{
    var task = Task.Factory.FromAsync(
        _userEndpoint.PresenceServices.BeginPresenceQuery,
        _userEndpoint.PresenceServices.EndPresenceQuery,
        new[] { useridSIP },
        new[] { "state" });

   var results = await task;
   return results.ToList();
}
  1. 避免使用 async void,详见此处
  2. 仅在有对应的 await 时使用 async

这样,您就可以使用 await 并根据需要进行处理,如下所示:

private async Task SomeCaller(UserEndpoint endpoint, string useridSIP)
{
    var list = await GetNotifications(endpoint, useridSIP);
    // ... do stuff with it
}

更新1

请确保通过检查此处详细说明的State,确保PresenceServices确实可用。

只要端点的State属性设置为已建立,所有出席服务都对其可用。

此外,这里可能会有所帮助。


  1. 你说要省略 async,但是却没有省略它。
  2. 这样做行不通,EndPresenceQuery 返回的是 IEnumerable<RemotePresentityNotification>,所以要获取 List<T>,你需要在某个地方调用 ToList()(就像问题中的代码一样)。
- svick
给我所有的源代码,我可以更好地帮助你。 - David Pine
我不是楼主,我没有比你更多的代码访问权限。 - svick
这应该是你正在寻找的内容。 - David Pine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接