Asynchronous programming in a portable library

I am very confused about the new async stuff. I have a portable library implementing my model with some classes with virtual functions that I hope to use in ASP.NET, WPF, Windows Store, Silverlight 5, and Windows Phone 8. They can target WCF functionality, CSharp SQLite, or be overridden by platform-specific libraries for a local file.

How do I set it up now that synchronous programming is frowned upon in the Windows Store world? I tried adding async keywords, etc. Into a portable library for virtual functions, but it says that I don't have the required frameworks. How can I reuse this library without rewriting it? Is OOP programming completely dead now?

+3


source to share


2 answers


VS will happily allow async

in portable libraries targeting .NET 4.5 and Windows Store. If you need other platforms (especially .NET 4.0 and Silverlight 5), you need to install Microsoft.Bcl.Async .



If you need a link, the source is available for my AsyncEx library ; the main assembly is a portable library that depends on Microsoft.Bcl.Async.

+2


source


The way I refer to it is to use a helper class that I adapted from a previous version. Basically:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml;

namespace JTModelsWinStore.Local
{
    public delegate void UseDataDelegate(DataCoordinator data);
    public delegate bool GetDataDelegate(DataCoordinator data);

    public class DataCoordinator
    {
        public DependencyObject Consumer;
        public GetDataDelegate GetDataFunction;
        public UseDataDelegate UseDataFunction;
        public bool GetDataSucceeded;
        public Exception ErrorException;
        public string ErrorMessage;

        public DataCoordinator(
            DependencyObject consumer,
            GetDataDelegate getDataFunction,
            UseDataDelegate useDataFunction)
        {
            Consumer = consumer;
            GetDataFunction = getDataFunction;
            UseDataFunction = useDataFunction;
            GetDataSucceeded = false;
            ErrorException = null;
            ErrorMessage = null;
        }

        public Task GetDataAsync()
        {
            GetDataSucceeded = false;

            Task task = Task.Factory.StartNew(() =>
            {
                if (GetDataFunction != null)
                {
                    try
                    {
                        GetDataSucceeded = GetDataFunction(this);
                    }
                    catch (Exception exception)
                    {
                        GetDataSucceeded = false;
                        ErrorException = exception;
                        ErrorMessage = exception.Message;
                    }
                }

                if (UseDataFunction != null)
                {
                    if (Consumer != null)
                    {
                        var ignored = Consumer.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                        {
                            UseDataFunction(this);
                        });
                    }
                    else
                        UseDataFunction(this);
                }
            });
            return task;
        }
    }
}

      

and then in your windows store code:



private async void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
    DataCoordinator data = new DataCoordinator(this, Logon, LogonCompleted);
    await data.GetDataAsync();
}

private bool Logon(DataCoordinator data)
{
    LoggedOnUserID = ServiceClient.LogOn(UserName, Password);

    if (LoggedOnUserID == null)
    {
        UserName = "AnonymousUser";
        Password = "";

        if (!String.IsNullOrEmpty(ServiceClient.ErrorMessage))
            data.ErrorMessage = "Log on failed.";

        return false;
    }

    if (!String.IsNullOrEmpty(ServiceClient.ErrorMessage))
    {
        data.ErrorMessage = ServiceClient.ErrorMessage;
        return false;
    }

    return true;
}

private void LogonCompleted(DataCoordinator data)
{
    if (data.GetDataSucceeded && LoggedOnUserID != null)
        pageTitle.Text = "Logged On";
    else
        pageTitle.Text = "LogOn Failed";
}

      

I provide the helper with two functions, one for getting data (slow) and one for doing something with the data in the UI. I know I can do this in two nested lambdas, but I like to hide two lambdas, which is more convenient for an old timer like me.

Please feel free to criticize it, both for others and for my own.

0


source







All Articles