怎么将异步方法封装为同步方法?

Nick_Ngai 2014-01-24 11:34:01
private void BindData()
{
ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient spaClient = new ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient();
spaClient.getPatientDetailCompleted += new EventHandler<ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs>(spaClient_getPatientDetailCompleted);
spaClient.getPatientDetailAsync("1,2");
}
catch (Exception ex)
{
throw ex;
}
}
}

private void spaClient_getPatientDetailCompleted(object sender, ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs e)
{
try
{
if (e.Error == null && e.Result != null)
{
ServiceForSchPatientAdmission.WebServicePatientVo[] result = e.Result; //只能在这里拿到结果
}
}
}

上面是一个异步的方法,我想将BindData()封装为一个可以调用的同步方法,怎么能够实现?
...全文
1105 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
Nick_Ngai 2014-04-03
  • 打赏
  • 举报
回复
下面是转同步方式,感觉还是个异步: delegate void DownDelegate(string s); //定义委托,非UI线程需要与UI线程通讯,必须通过委托 DownDelegate downDelegate; string html; AutoResetEvent done = new AutoResetEvent(false); public void CompletedDown(string s) { 获取数据= s; } private void Show_Click(object sender, System.Windows.RoutedEventArgs e) { downDelegate = CompletedDown; Thread t = new Thread(new ThreadStart(ThreadProc)); t.Start(); } public void ThreadProc() { WebClient webClient = new WebClient(); webClient.Headers[HttpRequestHeader.Cookie] = GetCookieContainer().ToString(); webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted); webClient.DownloadStringAsync(new Uri("http://www.baidu.com")); done.WaitOne(); //等待,收到通知后继续执行 this.Dispatcher.BeginInvoke(downDelegate, html); } private void webClient_DownloadStringCompleted(Object sender, DownloadStringCompletedEventArgs e) { html = e.Result; done.Set(); //通知线程继续执行 }
wuhaipinm 2014-02-10
  • 打赏
  • 举报
回复
引用 20 楼 sp1234 的回复:
其实如果你编程有一段时间了,那么动一动脑筋就能想到,以.net这种有这10几年历史(而微软的平台有着20几年历史)的平台来说,不可能告诉你什么while循环那种东西,而没有高效简洁的信号通知机制。
所谓的高效简洁,也是.net帮你封装,只简洁不一定高效,c++没这些就没法实现了?
Nick_Ngai 2014-02-07
  • 打赏
  • 举报
回复
引用 6 楼 wayu002 的回复:
[quote=引用 4 楼 anboat 的回复:] [quote=引用 3 楼 wayu002 的回复:] 这个还怎么详细呢?先创建一个AutoResetEvent event,调用完spaClient.getPatientDetailAsync("1,2")以后,就event.WaitOne()一直等待吧,等你的spaClient_getPatientDetailCompleted被异步调用的时候,重置event,event.Set(),然后bindData函数就可以继续执行了,你要得到返回值就把异步函数里面的结果保存起来,在bindData里面使用就可以了
我试过了,在event.WaitOne()这里就卡住了。[/quote] 关键是看你的这个getPatientDetailAsync是怎么实现的了,要是异步其他线程调用应该没问题,如果要是会串行到主线程里调用那肯定会卡住啊[/quote]
引用 19 楼 sp1234 的回复:
[quote=引用 17 楼 anboat 的回复:] 1.while(!isComplete){ }这是个死循环。 2.改为while(isComplete){ },这样也是不符合逻辑的,先执行完BindData()方法,不可能再回到while(isComplete)。
大概只能想象出什么“while循环”的基本都是自学的然后在花钱4个月培训只为拿个实习机会。 线程同步(线程阻塞)有几种不同的模式。例如 lock(){ }结构,例如 ManualResetEvent 类型对象,等等。建议你先把这两个熟悉了。[/quote] 多谢几位大哥。我这程序是串行的,那这样应该使用ManualResetEvent这种方式也不行了。 还有没有办法?
wuhaipinm 2014-01-29
  • 打赏
  • 举报
回复
引用 7 楼 anboat 的回复:
[quote=引用 5 楼 wuhaipinm 的回复:]

bool isComplete=false;
ServiceForSchPatientAdmission.WebServicePatientVo[] result ;
private ServiceForSchPatientAdmission.WebServicePatientVo[] BindData()
{
isComplete=false;
ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient spaClient = new ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient();
                spaClient.getPatientDetailCompleted += new EventHandler<ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs>(spaClient_getPatientDetailCompleted);
                spaClient.getPatientDetailAsync("1,2");
while(!isComplete){
}
return result ;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
}

        private void spaClient_getPatientDetailCompleted(object sender, ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs e)
        {
            try
            {
                if (e.Error == null && e.Result != null)
                {
                    ServiceForSchPatientAdmission.WebServicePatientVo[] result = e.Result; //只能在这里拿到结果
isComplete=true;
                }
            }
        }
试试
不行的,先执行完BindData()方法,再执行spaClient_getPatientDetailCompleted,完就结束了,不会再次进入到BindData()。所以while(!isComplete){ } return result ; } catch (Exception ex) { throw ex; } } }是没用的[/quote] 你试过没有,这样是可以的
Nick_Ngai 2014-01-29
  • 打赏
  • 举报
回复
1.while(!isComplete){ }这是个死循环。 2.改为while(isComplete){ },这样也是不符合逻辑的,先执行完BindData()方法,不可能再回到while(isComplete)。
  • 打赏
  • 举报
回复
其实如果你编程有一段时间了,那么动一动脑筋就能想到,以.net这种有这10几年历史(而微软的平台有着20几年历史)的平台来说,不可能告诉你什么while循环那种东西,而没有高效简洁的信号通知机制。
  • 打赏
  • 举报
回复
引用 17 楼 anboat 的回复:
1.while(!isComplete){ }这是个死循环。 2.改为while(isComplete){ },这样也是不符合逻辑的,先执行完BindData()方法,不可能再回到while(isComplete)。
大概只能想象出什么“while循环”的基本都是自学的然后在花钱4个月培训只为拿个实习机会。 线程同步(线程阻塞)有几种不同的模式。例如 lock(){ }结构,例如 ManualResetEvent 类型对象,等等。建议你先把这两个熟悉了。
iloli 2014-01-29
  • 打赏
  • 举报
回复
在调用异步方法的线程中使用轮询并等待异步的返回。这样每次循环检查方法有没有完成,如果没有 重新等待检查,等待一定要SLEEP 20-100毫秒,这个根据自己要求去设。。如果没有这几十毫秒时间,那将会造成假死
Nick_Ngai 2014-01-28
  • 打赏
  • 举报
回复
引用 14 楼 xxdddail 的回复:
使用同步对象来控制。比如互斥对象Mutex,同步锁Lock等。
不太明白,能详细点吗?
Nick_Ngai 2014-01-28
  • 打赏
  • 举报
回复
引用 10 楼 caozhy 的回复:
按理说,一个合理的api,都应该在提供异步方法的同时提供同步版本,而且天然地,它们的方法名应该成对出现,xxx()和xxxAsync()。 将异步改为同步的关键是在callback中设置一个信号,主程序在调用了异步方法后阻塞等待这个信号。
版主,我这里面没有提供同步版本,只有xxxAsync()。这样有办法吗?
_学而时习之_ 2014-01-28
  • 打赏
  • 举报
回复
使用同步对象来控制。比如互斥对象Mutex,同步锁Lock等。
qldsrx 2014-01-27
  • 打赏
  • 举报
回复
想要不卡住就只能异步,想要同步必定会卡住
Nick_Ngai 2014-01-27
  • 打赏
  • 举报
回复
引用 5 楼 wuhaipinm 的回复:

bool isComplete=false;
ServiceForSchPatientAdmission.WebServicePatientVo[] result ;
private ServiceForSchPatientAdmission.WebServicePatientVo[] BindData()
{
isComplete=false;
ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient spaClient = new ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient();
                spaClient.getPatientDetailCompleted += new EventHandler<ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs>(spaClient_getPatientDetailCompleted);
                spaClient.getPatientDetailAsync("1,2");
while(!isComplete){
}
return result ;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
}

        private void spaClient_getPatientDetailCompleted(object sender, ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs e)
        {
            try
            {
                if (e.Error == null && e.Result != null)
                {
                    ServiceForSchPatientAdmission.WebServicePatientVo[] result = e.Result; //只能在这里拿到结果
isComplete=true;
                }
            }
        }
试试
不行的,先执行完BindData()方法,再执行spaClient_getPatientDetailCompleted,完就结束了,不会再次进入到BindData()。所以while(!isComplete){ } return result ; } catch (Exception ex) { throw ex; } } }是没用的
小猪八Q 2014-01-27
  • 打赏
  • 举报
回复
引用 10 楼 caozhy 的回复:
按理说,一个合理的api,都应该在提供异步方法的同时提供同步版本,而且天然地,它们的方法名应该成对出现,xxx()和xxxAsync()。 将异步改为同步的关键是在callback中设置一个信号,主程序在调用了异步方法后阻塞等待这个信号。
非常赞同
threenewbee 2014-01-27
  • 打赏
  • 举报
回复
按理说,一个合理的api,都应该在提供异步方法的同时提供同步版本,而且天然地,它们的方法名应该成对出现,xxx()和xxxAsync()。 将异步改为同步的关键是在callback中设置一个信号,主程序在调用了异步方法后阻塞等待这个信号。
Nick_Ngai 2014-01-27
  • 打赏
  • 举报
回复
引用 8 楼 qldsrx 的回复:
想要不卡住就只能异步,想要同步必定会卡住
那有什么办法能够得到返回结果?
Nick_Ngai 2014-01-24
  • 打赏
  • 举报
回复
引用 1 楼 wayu002 的回复:
使用AutoResetEvent或者ManualResetEvent, 在BindData里面wait event,在异步回调函数里面set event。
能详细点吗? 能够在BindData这里得到返回值?
wayu002 2014-01-24
  • 打赏
  • 举报
回复
使用AutoResetEvent或者ManualResetEvent, 在BindData里面wait event,在异步回调函数里面set event。
wayu002 2014-01-24
  • 打赏
  • 举报
回复
引用 4 楼 anboat 的回复:
[quote=引用 3 楼 wayu002 的回复:] 这个还怎么详细呢?先创建一个AutoResetEvent event,调用完spaClient.getPatientDetailAsync("1,2")以后,就event.WaitOne()一直等待吧,等你的spaClient_getPatientDetailCompleted被异步调用的时候,重置event,event.Set(),然后bindData函数就可以继续执行了,你要得到返回值就把异步函数里面的结果保存起来,在bindData里面使用就可以了
我试过了,在event.WaitOne()这里就卡住了。[/quote] 关键是看你的这个getPatientDetailAsync是怎么实现的了,要是异步其他线程调用应该没问题,如果要是会串行到主线程里调用那肯定会卡住啊
wuhaipinm 2014-01-24
  • 打赏
  • 举报
回复

bool isComplete=false;
ServiceForSchPatientAdmission.WebServicePatientVo[] result ;
private ServiceForSchPatientAdmission.WebServicePatientVo[] BindData()
{
isComplete=false;
ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient spaClient = new ServiceForSchPatientAdmission.schPatientAdmissionClinicServicesPortTypeClient();
                spaClient.getPatientDetailCompleted += new EventHandler<ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs>(spaClient_getPatientDetailCompleted);
                spaClient.getPatientDetailAsync("1,2");
while(!isComplete){
}
return result ;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
}

        private void spaClient_getPatientDetailCompleted(object sender, ServiceForSchPatientAdmission.getPatientDetailCompletedEventArgs e)
        {
            try
            {
                if (e.Error == null && e.Result != null)
                {
                    ServiceForSchPatientAdmission.WebServicePatientVo[] result = e.Result; //只能在这里拿到结果
isComplete=true;
                }
            }
        }
试试
加载更多回复(2)

111,092

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧