Tag Archives: Asynchronous

Short Walks – Using JoinableTaskFactory

While attending DDD North this year, I attended a talk on avoiding deadlocks in asynchronous programming. During this talk, I was introduced to the JoinableTaskFactory.

This became strangely useful very quickly, when I encountered a problem similar to that described here. There are a couple of solutions to this question, but the least code churn is to simply make the code synchronous; however, if you do that by simply adding

.GetAwaiter().GetResult()

to the end of the async calls, you’re very likely to result in a deadlock.

One possible solution is to wrap the call using the JoinableTaskFactory, in the following way:

var jtf = new JoinableTaskFactory(new JoinableTaskContext());
var result = jtf.Run<DataResult>(() => _myClass.GetDataAsync());

This allows the task to return on the same synchronisation context without causing a deadlock.

References

https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.threading.joinabletaskfactory

https://stackoverflow.com/questions/33913836/how-to-render-a-partial-view-asynchronously

Cannot change thread mode after it is set

I recently published this article on using asynchonous methods within a Windows Game, and this article on enabling consumables within a Windows Game

However, I encountered a problem when I tried to use these two methods in combination. My code looked something like this:

var result = MessageBoxHelper.MsgBox.ShowAsync(string.Format("You do not have sufficient widgets for this.\n" +
    "Would you like to purchase more?"), MessageBoxButton.YesNo).ContinueWith(async (answer) =>
{
    if (answer.Result == MessageBoxResult.Yes)
    {
        bool purchTask = await Purchase.RequestProductPurchase(WIDGETS);

However, when I ran this; I got the following exception:

cannotchangethread

This is a marginally documented error:

By Microsoft and by Stack Overflow

I could call the function Purchase.RequestProductPurchase directly, but not, for some reason, in conjunction with ContinueWith. I tried this combination in a basic console application:

        static void Main(string[] args)
        {
            continueWithTest();
        }

        private static void continueWithTest()
        {
            MyAsyncFunc().ContinueWith(async (a) =>
            {
                Console.WriteLine("test");
                await Task.Delay(2000);                
            }).Wait();
            Console.ReadLine();
        }
        static async Task MyAsyncFunc()
        {
            await Task.Delay(2000);
            Console.WriteLine("Test1");
    }

And it worked fine. Based on what is available to read on the web, it looks like the threading model is, in some way, different when using ContinueWith. Although, it would appear that if you specify the TaskScheduler.Current, you should be able to use this in place of await, but that seems to make no difference.

The fix, as so many people are quick to point out, is use await:

        private void MakePurchase(int cost, Action onSuccess, bool interactive)
        {
            if (App.settings.CashPot.Total > cost)
            {
                App.settings.CashPot.Total -= cost;
                onSuccess.Invoke();                
            }
            else if (interactive)
            {
                InsufficientFunds(cost, onSuccess);
            }
        }


        private async void InsufficientFunds(int cost, Action onSuccess)
        {
            var result = await MessageBoxHelper.MsgBox.ShowAsync(string.Format("You do not have sufficient funds for this.\n" +
                "Would you like to purchase additional cash?"),
                "Insufficient Funds", MessageBoxButton.YesNo);                
                            
            if (result == MessageBoxResult.Yes)
            {
                bool purchTask = await Purchase.RequestProductPurchase(WIDGETS);

                MakePurchase(cost, onSuccess, false);
            }
        }

Using Asynchronous methods within a Windows Game

The new async / await syntax in .NET 4.5 + makes asynchronous programming really easy. However, there are times when having an assumption of asynchrony can impede you. One such example is programming for games (see my post on why you might want to avoid this).

However, what happens when you want to display a windows message box, or some other action that is asynchronous; See my post on a message box helper for an example.

In my particular case, I was to show a message box asynchronously, and perform a certain action based on the result; however, I don’t want to stop the game, and I don’t want to have to introduce an async / await into the programming model (for reasons in the linked post).

My solution was to use a combination of two, slightly outdated, methods of asynchronous programming: call backs and continuation blocks (strictly speaking, async / await does use continuation blocks behind the scenes admittedly). The following code will attempt to make an in-app purchase from the store:

        internal static async Task<bool> PurchaseCash()
        {
            var result = await Windows.ApplicationModel.Store.CurrentApp.RequestProductPurchaseAsync(PURCHASE);
            return (result.Status == ProductPurchaseStatus.Succeeded);
        }

What that function actually does it not important; however, it needs to be called from within a game loop. Here’s how it is called:


                        Purchase.PurchaseCash().ContinueWith((purchaseTask) =>
                        {
                            purchaseTask.Wait();
                            if (purchaseTask.Result)
                            {
                                App.settings.CashPot.Total += Purchases.Purchase.MORE_CASH_AMOUNT;
                            }

                        });

This will only execute the purchase action if the purchase was successful; it’s completely asynchronous, and it doesn’t affect the main thread. All well and good, but what if, instead of a specific task, we wanted to execute a conditional command; for example: when the purchase is called, we want to turn on a specific feature.

In this case, I decided to use a call back; the method signature looks like this:

        private bool MakePurchase(int cost, Action onSuccess)

And it is called like this:

                    if (!App.settings.Purchase1)
                    {
                        MakePurchase(PURCHASE1_COST, () =>
                        {
                            App.settings.Feature1 = true;
                        });
                    }

Inside MakePurchase, I only call the onSuccess method where the purchase was successful:

                        Purchase.PurchaseCash().ContinueWith((purchaseTask) =>
                        {
                            purchaseTask.Wait();
                            if (purchaseTask.Result)
                            {
                                onSuccess.Invoke();
                            }
                        }

Conclusion

The syntax above is nowhere near as clear and concise as a simple await statement; however, await statements can’t be used outside of an async method and, especially when programming games, that’s not always practical. The other thing that I haven’t mentioned here is exception handling – I may make that the subject of a later post.