Как правильно разрешить нескольким задачам доступ к файлу базы данных? - PullRequest
0 голосов
/ 21 января 2019

У меня есть сервер, который принимает несколько клиентских запросов в виде нескольких задач, которые нужно читать и записывать из файла базы данных Microsoft Access .mdb. Я полагал, что у меня будут операции по очереди сервера, когда они вызывают EnqueueWriteCommand и EnqueueReadCommand в качестве задач, а затем у меня будет другая отдельно запущенная задача (ExecuteTasks), запускающая поставленные в очередь задачи. Эта идея кажется безумно запутанной, но я не могу найти или найти лучший способ сделать это. Вот мой код ниже.

По результатам моего тестирования у меня возникает тупик в ExecuteTasks при вызове «await Task.Run (() => task)».

Что вызывает этот тупик? Правильна ли моя общая идея в решении этой проблемы с несколькими потоками? Есть ли лучший способ сделать это?

using System.Data.OleDb;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Diagnostics;

namespace appDatabaseConsole

{
/// <summary>
/// Contains all necessary components for initializing and interacting with 
    the database file.
/// </summary>
public static class DBHandler
{
    private static OleDbConnection c;
    private static OleDbDataReader reader;
    private static OleDbCommand command;

    private static List<Task> tasks;

    /// <summary>
    /// Initialize the connection of the OleDbConnection components to the database file.
    /// </summary>d
    public static void InitializeConnection()
    {
        c = new OleDbConnection
        {
            ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\AppDatabase.mdb"
        };
        command = new OleDbCommand
        {
            Connection = c
        };
        reader = null;

        tasks = new List<Task>();

        // Run the Task executor ask a separate task
        Task.Run(() => ExecuteTasks());
    }

    private async static Task ExecuteTasks()
    {
        while (true)
        {
            if (tasks.Count > 0)
            {
                Debug.WriteLine("tasks.Count exceeded zero");
                foreach (Task task in tasks)
                {
                    await Task.Run(() => task);
                    tasks.Remove(task);
                    Debug.WriteLine("Completed task and removed task.");
                }
            }
        }
    }

    public static void EnqueueWriteCommand(string commandText)
    {
        Debug.WriteLine("Start EnqueueWriteCommand");
        Task task = new Task(() => WriteCommand(commandText));
        tasks.Add(task);
        Debug.WriteLine("Finish EnqueueWriteCommand");
    }

    public static List<string>[] EnqueueReadCommand(string commandText, int numberOfColumns)
    {
        Debug.WriteLine("Start EnqueueReadCommand");
        Task<List<string>[]> task = new Task<List<string>[]>(() => ReadCommand(commandText, numberOfColumns));
        tasks.Add(task);

        Debug.WriteLine("Just before finishing EnqueueReadCommand");
        return task.Result;
    }

    private static void WriteCommand(string commandText)
    {
        Debug.WriteLine("Start WriteCommand");
        c.Open();
        command.CommandText = commandText;
        command.ExecuteNonQuery();
        c.Close();
        Debug.WriteLine("Finish WriteCommand");
    }

    private static List<string>[] ReadCommand(string commandText, int numberOfColumns)
    {
        Debug.WriteLine("Start ReadCommand");
        c.Open();
        command.CommandText = commandText;
        reader = command.ExecuteReader();

        List<string>[] data = new List<string>[numberOfColumns];
        for (int column = 0; column < numberOfColumns; column++)
        {
            while (reader.Read())
            {
                data[column].Add(reader[column].ToString());
            }
        }
        reader.Close();
        c.Close();
        Debug.WriteLine("Finish ReadCommand");
        return data;
    }
}

}

...