Home > Blockchain >  C# making sure a variable is updated before continuing the code
C# making sure a variable is updated before continuing the code

Time:12-02

Hi I'm kinda new to this, I'm trying to get this piece of code to run but I don't understand where it went wrong.

I need to make sure that "LatestDate" is updated before continuing the code and I've been told that using "await" won't work due to my method not being async.

Here's what I have so far.

basically what I'm trying to do is check if there are new data being added to the firebase data base under this user. and return a boolean flag accordingly.

public Boolean CheckWatchConnection()
    {
        var latestDate = 0;

        var Now = DateTimeOffset.Now.ToUnixTimeMilliseconds();

        Boolean Connected = false;

        DatabaseReference LastHistoryEnrty = DBreference.Child("users").Child(User.UserId).Child("History");

        var query = LastHistoryEnrty.OrderByKey().LimitToLast(1); 
            
            var snapshot = query.GetValueAsync().ContinueWith(task => {
                if (task.IsFaulted)
                {
                    // Handle the error...
                }
                else if (task.IsCompleted)
                {
                    DataSnapshot snapshot2 = task.Result;

                    latestDate = int.Parse(snapshot2.Child("Date").Value.ToString());
                }

            });

        await snapshot;
        
            long Diff = Now - latestDate;

            if (Diff < 10)
            {
                Connected = true;
            }
            else
            {
                Connected = false;
            };

            return Connected;

        

    }// end of Watch Connection

So far I've been getting 0 for "LatestDate" and I tried using snapshot.Wait(); but that blocked the main thread and made unity crash..Help is MUCH appreciated

CodePudding user response:

You can't wait for the snapshot to return from CheckWatchConnection, because Unity has to keep operating, drawing frames, and so on, so forget giving it a return type. Instead, pass an Action<bool> callback you can use with the result of latestDate.

public void CheckWatchConnection(Action<bool> callback)
{
    var latestDate = 0;

    var Now = DateTimeOffset.Now.ToUnixTimeMilliseconds();

    Boolean Connected = false;

    DatabaseReference LastHistoryEnrty = DBreference.Child("users").Child(User.UserId).Child("History");

    var query = LastHistoryEnrty.OrderByKey().LimitToLast(1); 
        
    var snapshot = query.GetValueAsync().ContinueWith(task => {
        if (task.IsFaulted)
        {
            // Handle the error...
        }
        else if (task.IsCompleted)
        {
            DataSnapshot snapshot2 = task.Result;

            latestDate = int.Parse(snapshot2.Child("Date").Value.ToString());
            long Diff = Now - latestDate;

            if (Diff < 10)
            {
                Connected = true;
            }
            else
            {
                Connected = false;
            }
            callback(Connected);
        }
    });
 
}// end of Watch Connection

Then where you call CheckWatchConnection, take whatever is waiting on the results (example):

// before
bool connected = CheckWatchConnection();

Debug.Log($"Connected: {connected}");

/* more stuff with connected */

And put that logic into the callback

// after
CheckWatchConnection( connected => {
    Debug.Log($"Connected: {connected}");

    /* more stuff with connected */
});

CodePudding user response:

I recommend you read this asynchronous programming guide by Microsoft. The main goal of asynchronous programming is to achieve efficient use of resources. async-await and Tasks are the main tools for easy to write and easy to understand asynchronous code.

As a very general rule, a method that calls an asynchronous method has to be asynchronous itself, unless it is kind of fire and forget and you don't care about the result of the asynchronous call. So in your code, CheckWatchConnection should be async, because it calls GetValueAsync. In order to make your method async, you have to change the return type from T to Task<T>, or just Task if your method returns void. In your case, it would be Task<Boolean>.

If you want to wait for an async call to finish, the easiest thing to do is using await..

var snapshot = await query.GetValueAsync();
latestDate = int.Parse(snapshot.Child("Date").Value.ToString()); 

To use await, you have to mark your method as async. So finally, the signature of the method could look like

public async Task<Boolean> CheckWatchConnectionAsync() 

And the whole thing:

public async Task<Boolean> CheckWatchConnectionAsync()
{
    var latestDate = 0;

    var Now = DateTimeOffset.Now.ToUnixTimeMilliseconds();

    Boolean Connected = false;

    DatabaseReference LastHistoryEnrty = DBreference.Child("users").Child(User.UserId).Child("History");

    var query = LastHistoryEnrty.OrderByKey().LimitToLast(1); 
        
    var snapshot = await query.GetValueAsync();
    latestDate = int.Parse(snapshot.Child("Date").Value.ToString());

        long Diff = Now - latestDate;

        if (Diff < 10)
        {
            Connected = true;
        }
        else
        {
            Connected = false;
        };

        return Connected;
}
  • Related