最近项目中需要循环进行网络请求拉取用户信息(每个用户信息都需要一次网络请求),拉取完成后需要通知界面更新UI。实现方法是使用C#提供的ManualResetEvent,相当于一个标记,在每个线程中插入这个标记。再启动一个线程循环监听这个标记,直到所有线程都执行完毕则更新UI。
public List<WxUserInfo> GetAllUerInfo(StringCollection userlist)
{
WxUserList = new List<WxUserInfo>();
//为每个线程创建一个ManualResetEvent对象
_ManualEvents = new ManualResetEvent[userList.Count];
int i = 0;
foreach (string openid in userList)
{
_ManualEvents[i] = new ManualResetEvent(false);
WXOBJ wxobj = new WXOBJ(_ManualEvents[i], openid);
i++;
//加入线程池
ThreadPool.QueueUserWorkItem(new WaitCallback(GetUserInfo), (object)wxobj);
}
//再启动一个线程监听其他线程执行状态
Thread t = new Thread(NotifyUI);
t.Start();
return WxUserList;
}
private void NotifyUI(object obj)
{
//等待所有线程释放_ManualEvents
WaitHandle.WaitAll(_ManualEvents);
//监听线程有时会抢先通知UI更新,所以这里让线程睡了1秒才通知更新
Thread.Sleep(1000);
WxUserInfo[] allWxUser = WxUserList.ToArray();
//切换UI线程更新UI
Action<DataGrid, List<WxUserInfo>> updateAction = new Action<DataGrid, List<WxUserInfo>>(UpdateListView);
Information.Dispatcher.BeginInvoke(updateAction, Information, allWxUser.ToList());
var suto = new ManagerService.ManagerServiceClient().InsertWxUserInfoAsync(allWxUser);
}
/// <summary>
/// 创建一个对象封装manualResetEvent,和线程方法需要的参数
/// </summary>
public class WXOBJ
{
public ManualResetEvent manualResetEvent { set; get; }
public string openid { set; get; }
public WXOBJ(ManualResetEvent manualResetEvent, string openid)
{
// TODO: Complete member initialization
this.manualResetEvent = manualResetEvent;
this.openid = openid;
}
}