如何等待异步?

qq1119753812 2010-06-14 10:05:48
可能我说的不是太清楚,还是让我们直接看代码吧

public static bool Reg(string _name, string _password)
{
//……

EntityQuery<User> query = from m in db.GetUserQuery()
where m.Name == _name
select m;
_users = db.Load(query, onCompleted, null);
//我在这里向等待回调函数返回的结果,好确定是不是数据库里已经有_name的同名注册,才可以确定该函数最终的布尔值
//现在的问题是应该来等待呢?
//……
}
private static void onCompleted(LoadOperation<User> U)
{
//…………
}
...全文
302 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
itmrcao 2011-10-25
  • 打赏
  • 举报
回复
虽然我是新人,有很多代码解决了问题。但是我也想提个问题,
lo.Completed += new EventHandler(lo_Completed);
此代码意思是不是等待回调完毕之后出发此事件?如果是的话,我定义一个新增的BUTTON在BUTTON触发点击事件的时候等他回调完毕触发事件,但是我BUTTON后续代码还是运行了。我理解楼主的意思 是否真的只有挂起才能解决问题,我也是这问题弄的走火入魔了。也没有实际的DEMO
qq1119753812 2010-06-19
  • 打赏
  • 举报
回复
就是说还是要我自己去建立个WCF服务吗?
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
觉得不是异步不异步的问题,而是LZ自己设计的问题。

不使用 WCF RIA Services 的做法是会在 WCF 端公开一个服务,如

[OperationContract]
public bool HasUserNameExisted(string name)
{
...
}


使用了 WCF RIA Services ,为何就不这样做呢? 在服务端多创建一个方法不就解决了,
光有一个 GetUserQuery() 方法是不够的。
海涵德 2010-06-19
  • 打赏
  • 举报
回复
楼主不要走的那么远,我看你都使用了线程的概念了,没那么复杂,有些事情系统都为你做好了,实际上把异步结构搞明白了就够用了:

1. 编写一个服务安装在服务端
2. 在应用程序中引用这个服务
3. 在应用程序中请求这个服务
4. 在应用程序中通过事件等待这个服务的结果
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
对,14楼的代码有道理
private void onCompleted(LoadOperation<User> U)
中的这个 U 应是一个可列举的集合, 不能通过判断是否为 null 来检查用户名是否存在。

不过,最合理的做法还是
在定义 GetUserQuery() 的文件中,再定义一个 public bool HasUserNameExisted(string name)。

给出示范代码

public bool HasUserNameExisted(string name)
{
return this.ObjectContext.Users.Any( u = > u.Name.ToLower() == name.Trim().ToLower() );
}


嗯, LoadOperation<TEntity> 公布了 Completed 事件, 向Joetao学习
qq1119753812 2010-06-19
  • 打赏
  • 举报
回复
让我消化下,我回去想想哦
先来给分结贴,要是再迷糊,再向你请教
Joetao 2010-06-19
  • 打赏
  • 举报
回复
直接放到onCompleted(LoadOperation<User> U)方法中,参照这段代码就可以了

private void button1_Click(object sender, RoutedEventArgs e)
{
var query = from s in client.GetStudentsQuery() select s;
LoadOperation<ScoreManagement.Web.Student> lo = client.Load(query);
lo.Completed += new EventHandler(lo_Completed);
}

void lo_Completed(object sender, EventArgs e)
{
LoadOperation<ScoreManagement.Web.Student> lo = (LoadOperation<ScoreManagement.Web.Student>)sender;
if (lo.Entities.Count() > 0)
{
ScoreManagement.Web.Student student = lo.Entities.FirstOrDefault();
this.textBlock1.Text = student.StudentID.ToString();

}

}



Sunpire 2010-06-19
  • 打赏
  • 举报
回复
private static void onCompleted(LoadOperation<User> U)
改为
private void onCompleted(LoadOperation<User> U)
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 qq1119753812 的回复:]
那么现在我用WCF RIA Services如何先让函数在那里等待呢?LoadOperation<TEntity>类型的变量,有iscompleted属性,但是我是不是应该先让主线程挂起呢?
[/Quote]
我在8楼和9楼中说了,直接在

private static void onCompleted(LoadOperation<User> U)
{
// 在这里对U进行判断,以断定 name 是否已被使用了,
// 根据逻辑,是不是
if( U != null )
{
判断出用户名已存在
}
else
{
}
}



LZ,委托和事件你都明白吧?我在11的代码你能明白么?
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
使用语法上的区别:

WCF异步调用, XXXCompleted 公布为事件

client.GetUsersCompleted += new EventHandler<GetUsersCompletedEventArgs>(client_GetUsersCompleted);
client.GetUsersAsync();

void client_GetUsersCompleted(object sender, GetUsersCompletedEventArgs e)
{
// 异步调用结束
// 检查 e.Error ,判断是否有异常发生,
// 如果没有异常,则可以使用 e.Result
}


WCF RIA 异步调用, Completed 没有被公布为事件,而只是一个参数,一个 Action委托。

_OrganizationContext.Load(_OrganizationContext.GetUsersQuery(), OnGetCompleted , null);

void OnGetCompleted(LoadOperation<User> result)
{
// 但是这里似乎判断不了异常
}


不管是哪种异步调用,等待异步调用完成都不是通过循环来等待的,而是通过委托
qq1119753812 2010-06-19
  • 打赏
  • 举报
回复
那么现在我用WCF RIA Services如何先让函数在那里等待呢?LoadOperation<TEntity>类型的变量,有iscompleted属性,但是我是不是应该先让主线程挂起呢?
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
WCF RIA Services 我是几乎没有使用,一个 Walkthrough 的教程都没有看完就在抵制它。

System.Threading.SendOrPostCallback 这个是 WCF 异步调用的东东,
不是 WCF RIA Services 的。

WCF RIA Services 异步调用的 callback 已经被包装得完全像是回调函数了,
类型为 Action<LoadOperation<TEntity>> 或 Action<InvokeOperation<基元类型>> 的回调函数,

LZ直接在回调函数中写代码就OK了,这点和WCF异步调用本质上是相同的 ---- 都是委托 ,前者是委托,后者是事件
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
抛开业务逻辑上的合理性而言,不增加public bool HasUserNameExisted(string name) 方法,
仅按照LZ的做法也是可以的。


//
// 摘要:
// Initiates a load operation for the specified query.
//
// 参数:
// query:
// The query to invoke.
//
// callback:
// Optional callback to be called when the load operation completes.
//
// userState:
// Optional user state.
//
// 类型参数:
// TEntity:
// The entity Type being loaded.
//
// 返回结果:
// The load operation.
public LoadOperation<TEntity> Load<TEntity>(EntityQuery<TEntity> query, Action<LoadOperation<TEntity>> callback, object userState) where TEntity : Entity;


也就是说LZ在顶楼的代码中

private static void onCompleted(LoadOperation<User> U)
{
// 在这里对U进行判断,以断定 name 是否已被使用了
}


如果是使用 public bool HasUserNameExisted(string name)
则这个 callback 的类型是 Action<InvokeOperation<bool>> callback ,
而不是 Action<LoadOperation<TEntity>> ,逻辑意义更为明确
qq1119753812 2010-06-19
  • 打赏
  • 举报
回复
确实,我真的被这个问题弄得走火入魔了
请问下,System.Threading.SendOrPostCallback 这个怎么用?能给个范例看看吗?

同时谢谢sunpire不倦的答复
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qq1119753812 的回复:]
就是说还是要我自己去建立个WCF服务吗?
[/Quote]

不是,使用了 WCF RIA Services,就不用再创建单纯的 WCF 服务了。

是说在定义 GetUserQuery() 的文件中,再定义一个 public bool HasUserNameExisted(string name)
Sunpire 2010-06-19
  • 打赏
  • 举报
回复
看了LZ这段代码了,简直就是无话可说

static bool flagIsCompleted;
public static bool Reg(string _name, string _password)
{
…………
_users = db.Load(query, onCompleted, null);

bool flag = false;
int i = 0;
System.Threading.Thread.Sleep(3000);
while ( flag == false&& i <5)
{
flag = _users.IsComplete;
i++;
MessageBox.Show(n.ToString());
}
…………
}


希望冷大神早日把 WCF RIA Services 的教程写出来吧,
没有 Silverlight + WCF 的基础,也没有委托、事件的基础,LZ 学 Silverlight + WCF RIA Services 都快走火入魔了。

异步调用是不能通过循环来等待异步调用完成的,而且也是不一定能等得到,比如异步的过程中出错了、服务关闭了,那循环还能等得到结果吗?
导步调用是通过 System.Threading.SendOrPostCallback 这个委托来通知调用者调用完成的,用起来一点也不麻烦,从代码上看就像是使用事件一样。
qq1119753812 2010-06-15
  • 打赏
  • 举报
回复
我自己顶下 请问
youngyey 2010-06-14
  • 打赏
  • 举报
回复
同问~~~~~~~~~~~

8,735

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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