我很欣赏GetAsync,异步,但是我找不到任何关于如何使用它的文档。在这个阶段,我想要的是获取我的名字并将其分配给文本块。当然,如果我在_fbClient.GetCompleted + = / _fbClient.GetAsync(“/ me”)块中执行此操作,则会收到无效的跨线程访问异常错误。
在下面的代码中,NameTextBlock控件当然设置为“[EMPTY]”,稍后一段时间标记为=======>执行会导致错误。
我见过的几个例子使用了似乎是同步的Get方法,但似乎已经消失了(我不想再用它)。
string name = "EMPTY";
try
{
_fbClient.GetCompleted +=
(o, e) =>
{
if (e.Error == null)
{
var result = (IDictionary<string, object>)e.GetResultData();
//Dispatcher.BeginInvoke(() => MyData.ItemsSource = result);
var tempname = (string)result["name"];
name = (string)result["name"];
NameTextBlock.Text = "[" + name + "]";
}
else
{
MessageBox.Show(e.Error.Message);
}
};
_fbClient.GetAsync("/me");
//======> NameTextBlock.Text = "[" + name + "]";
}
catch
{
MessageBox.Show("Failed.. deal with issues.");
}
finally
{
NameTextBlock.Text = "[" + name + "]";
}
答案 0 :(得分:1)
你遇到的问题是racing condition的组合,而且非Gui线程正在尝试更改UI元素(我忘记了正确的术语)。
在WPF中,您使用Dispatcher模式来解决第二个问题。在Winforms中,您使用InvokeRequired模式。
在打电话之前打击比赛条件
_fbClient.GetAsync("/me");
将NameTextBlock.Text设置为“loading ...”或“fetching ...”或其他类似的效果。这样,当异步调用完成时,它可以使用正确的详细信息填充文本框。您可能还想更改样式以使其对用户更明显(如加载时为灰色,结果时为亮红色)。你现在正在做的是假设当你将文本框的文本设置为name变量时,事件(异步调用)已经完成。这可能是也可能不是这样!
以更简单的方式想象它。两个人在一个车库。你发一个打开车库门,另一个打车去车库。在你当前的代码中,驾驶面包车的人开车进入车库而不是检查或关心车库门是否打开。
您遇到的下一个问题是Thread Safety。 “name”变量可以同时读取和分配,这意味着读取操作可以在易失性存储器上运行,并且很可能导致错误/问题 - 特别是在较大规模上!
我建议你看看Thread Synchronization以获得更好的主意。
很多信息要在那里消化,抱歉。希望它有所帮助!
答案 1 :(得分:0)
您在所提供的代码段中有答案 使用Dispatcher.BeginInvoke方法,如下所示:
Dispatcher.BeginInvoke(() => NameTextBlock.Text = "[" + name + "]");