新手:使用GetAsync进行无效的跨线程访问

时间:2011-07-06 19:43:23

标签: c# facebook-c#-sdk

我很欣赏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 + "]";
        }

2 个答案:

答案 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 + "]");