Обеспечение того, чтобы объект, выполняющий длинную задачу, не восстанавливался - PullRequest
0 голосов
/ 23 мая 2018

У меня есть приложение WinForms, которое получает данные Car из файла базы данных Sqlite, который генерируется CSV-файлом из WebService, и связанные части для каждого автомобиля.При создании экземпляра класс Car заполняет все свойства из базы данных и получает много данных от WebService, для завершения которого требуется около 30 секунд, поэтому я просто вызываю асинхронную задачу после заполнения свойств базы данных и позволяю ей работать асинхронно.После того, как веб-служба возвращает все данные и вся работа выполнена, экземпляр сохраняется в списке List, который работает как внутренний кеш.

Все работает хорошо, пока пользователь не выполнит операцию над деталью, для которой требуется свойство ParentCarвозвращаться, пока метод WebService все еще работает, вызывая создание экземпляра нового Car и повторный опрос веб-службы столько раз, сколько запрашивается свойство, пока Car не существует в списке кэша.Это прекращается, как только первый экземпляр заканчивает обработку, но все изменения будут перезаписываться каждый раз, когда заканчиваются следующие экземпляры.

Я изо всех сил пытаюсь найти способ гарантировать, что экземпляр Car создается только один раз, не блокируяПользовательский интерфейс во время жизни приложения, есть идеи?

Это код, который у меня есть на данный момент:

public class Car
{
    private List<Part> _parts = new List<Part>();

    public string Id { get; private set; }
    public int DbIndex
    {
        get { return DbClass.GetCarIndexById(Id); }
    }
    public ReadOnlyCollection<Part> Parts { get => _parts.AsReadOnly(); }

    public Car(System.Data.SQLite.SQLiteDataReader sQLiteDataReader)
    {
        // Code to Load all properties from sQLiteDataReader

        Task.Run(() => LongRuningWebServiceTask());
    }

    private async Task LongRuningWebServiceTask
    {
        // Long running code that will populate even more properties

        SaveToInternalDb();
    }

    private void SaveToInternalDb()
    {
        if (DbIndex > -1)
            DbClass.UpdateCarData(this);
        else
            DbClass.AddCar(this);
    }

    public void RelateParts(IEnumerable<Part> parts)
    {
        _parts.AddRange(parts);
    }

    ~Car()
    {
        SaveToInternalDb();
    }
}

public class Part
{
    public string ParentCarId { get; private set; }
    public Car ParentCar
    {
        get
        {
            Task getCar = DbClass.GetCarById(ParentCarId);
            getCar.Wait();
            return getCar.Result;
        }
    }
}

public static class DbClass
{
    private static SQLiteConnection sqlConn;
    private readonly string sqlFile = "pathToDbFile";
    private static List<Car> CarCache = new List<Car>();

    public static async Task<Car> GetCarById(string> carId, bool ignoreCache = false)
    {
        Car foundCar = null;
        if (!ignoreCache)
            foundCar = CarCache.Find(s => s.Id == carId);

        if (foundCar == null)
        {
            try
            {
                string sql = string.Format("SELECT * FROM all_Cars WHERE Car = '{0}';", carId);
                using (SQLiteCommand command = new SQLiteCommand(sql, sqlConn))
                {
                    using (SQLiteDataReader reader = (SQLiteDataReader)await command.ExecuteReaderAsync())
                    {
                        while (await reader.ReadAsync())
                            foundCar = new Car(reader));
                    }
                }
            }
            catch (Exception e)
            {
                string m = e.Message;
            }

            if (foundCar != null)
            {
                var partsList = await GetPartsByCarId(carId);
                if (partsList.Count > 0)
                    Car.RelateParts(partsList);

                if (!ignoreCache)
                {
                    if (foundCar.DbIndex == -1)
                        CarCache.Add(foundCar);
                }
            }
        }

        return foundCar;
    }

    public static async Task<List<Part>> GetPartsByCarId(string carId)
    {
        List<Part> foundParts = new List<Part>();

        int index = GeCarIndexById(carId);
        Car foundCar = index > -1 ? CarCache[index] : null;
        if (foundCar != null)
            foundParts = await GetPartsByCarId(carId);

        return foundParts;
    }

    public static void InitiateSqlConnection()
    {
        if (sqlConn == null)
        {
            sqlConn = new SQLiteConnection("Data Source=" + sqlFile.FullName + ";Version=3;");
            try
            {
                sqlConn.Open();
            }
            catch (Exception e)
            {
                var m = e.Message;
            }
        }
        else
        {
            if(sqlConn.State == System.Data.ConnectionState.Broken || sqlConn.State == System.Data.ConnectionState.Closed)
                sqlConn.Open();
        }
    }

    public static int GetCarIndexById(string carId)
    {
        int index = -1;
        for(int c = 0; c < CarCache.Count;c++)
        {
            if(CarCache[c].Id == carId)
            {
                index = c;
                break;
            }
        }
        return index;
    }

    public static void AddCar(Car car)
    {
        CarCache.Add(car);
    }

    public static void UpdateCarData(Car car)
    {
        if(car != null)
        {
            int index = car.DbIndex;
            if(index > -1)
                CarCache[index] = car;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...