确保运行长任务的对象不会被重新实例化

时间:2018-05-23 16:50:40

标签: c# winforms

我有一个WinForms应用程序,它从Sqlite数据库文件中获取Car数据,该文件由WebService的CSV文件生成,以及每个Car的相关部件。实例化时,Car类填充数据库中的所有属性,并从WebService获取大量数据,大约需要30秒才能完成,所以我只需在填充数据库属性后调用异步任务,然后让它以异步方式运行。在Web服务返回所有数据并完成所有工作后,实例将保存在类似于内部缓存的List中。

一切正常,直到用户对部件进行操作,该部件需要在WebService方法仍在运行时返回属性ParentCar,从而导致新的Car被实例​​化并重新轮询Web服务多次属性是在缓存列表中不存在Car时请求。一旦第一个实例完成处理,它就会停止,但每次下一个实例完成时,所有更改都将被覆盖。

我很难找到一种方法来确保Car在实际应用期间没有阻止UI一次实例化,任何想法?

这是我目前的代码:

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;
        }
    }
}

0 个答案:

没有答案