暂停代码执行,直到某个变量为真

时间:2012-06-21 10:17:58

标签: c# json windows-phone

我正在忙于一个调用servlet的Windows Phone应用程序,然后该servlet返回JSON,然后转换为C#对象。

当用户点击按钮时执行此代码:

    //Login button pressed
    private void btnLogin_Click(object sender, RoutedEventArgs e)
    {

        //Get needed variables
        Doctor doctor = new Doctor();
        string userName = txtUsername.Text;
        string password = txtPassword.Text;

        if ((userName != "" || userName != null) && (password != "" || password != null))
        {
            //Log doctor in
            doctor.Login(userName, password);
        }
        else
        {
            MessageBox.Show("Please make sure all fields are filled out");
        }

        //If doctor has valid session ID, forward to search page
        if ((doctor.getOk() != "false") || (doctor.getOk() != "") && (doctor.getSessionID() != ""))
            NavigationService.Navigate(new Uri("/Search.xaml", UriKind.Relative));
            //MessageBox.Show("Ok: "+doctor.getOk()+"\nSessionID: "+doctor.getSessionID());
        else
            MessageBox.Show("Login failed, please check your username and password and try again");
    }

这是医生班:

public class Doctor
{
    string sessionID = "";
    string username = "";
    string password = "";
    string ok = "";

    public void Login(string argUsername, string argPassword){           

        if ((username != "" || username != null) && (password != "" || password != null))
        {
            //Set doctor username and password for later reference if necesarry
            this.username = argUsername;
            this.password = argPassword;

            //Url to login servlet
            string servletUrl = "http://196.3.151.36:8080/AuthService/login?u=" + username + "&p=" + password;

            //Calls Servlet
            WebClient client = new WebClient();
            client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(logonJsonDownloadComplete);
            client.DownloadStringAsync(new Uri(servletUrl, UriKind.Absolute));

        }

    }

    //Converts returned Json to C# Object
    private void logonJsonDownloadComplete(object sender, DownloadStringCompletedEventArgs e)
    {
        var jsonResponse = e.Result;
        var session = JsonConvert.DeserializeObject<Session>(e.Result);
        ok = session.ok;
        sessionID = session.sid;
        MessageBox.Show("Ok: " + ok + "\nSessionID: " + sessionID);
    }

    public string getOk()
    {
        return this.ok;
    }

    public string getSessionID()
    {
        return this.sessionID;
    }


}

这是会话类:

public class Session
{
    public string sid { get; set; }
    public Account account { get; set; }
    public string ok { get; set; }
    public string expiry { get; set; }
}

现在的问题是:当用户点击登录按钮时,会创建一个新的医生对象,然后在该医生对象上调用login()方法,然后又调用该servlet。成功下载json后,将在医生课程中调用 logonJsonDownloadComplete 方法。然后基本上接受json,并将其转换为几乎只有一堆getter和setter的会话对象。然后,login方法将医生变量(sessionID和ok)设置为会话对象中现在的任何变量。 (唷!)

但是当我在按钮点击事件中调用我的医生对象上的getOk()和getSessionID()时,它会返回空白字符串,就像从未设置变量一样。我认为这是因为代码可能是异步运行的?

如何在getOk()和getSessionID()语句之前暂停onclick方法中的代码,直到调用 logonJsonDownloadComplete 方法。这意味着已收到这些值......如果这有意义吗?

修改

另外值得一提的是,当我在logonJsonDownloadComplete方法中调用MessageDialog时,它可以工作,但是当我在click事件中调用它(当前已注释掉)时,它会返回空白变量。

2 个答案:

答案 0 :(得分:2)

您不希望实际暂停UI线程中的代码。你想要的是正常的UI事件(重新绘制等),但是在登录完成之前要禁用一些/所有其他控件。

基本上在编写WP7应用程序时,异步思考。你没有真正做Login - 你正在做BeginLogin。您需要在调用完成后将方法传递回执行,以及相关结果......然后您将进入下一个屏幕或其他任何屏幕。

请注意,异步目前相对比较麻烦,但使用C#5和.NET 4.5,它会通过async / await功能变得更简单很多

答案 1 :(得分:0)

我认为您正在寻找一个行动代表:http://msdn.microsoft.com/en-us/library/018hxwa8.aspx

在这里,我做了一个例子:

    public void IsStringEmpty(string input, Action<bool, Exception> callback)
    {
        try
        {
            if (string.IsNullOrEmpty(input)) callback(true, null);
            else callback(false, null);
        }
        catch (Exception ex)
        {
            callback(false, ex);
        }
    }

    public void Test()
    {
        string test = string.Empty;

        // show busy indicator here

        IsStringEmpty(test, (result, error) =>
        {

            //hide busy indicator here

            if (error == null)
            {
                if (result) { /* string is empty */}
                else { /* string is not empty */}
            }
            else
            {
                /* show/log error?*/
            }
        });
    }