如何正确允许多个任务访问数据库文件?

时间:2019-01-21 06:19:11

标签: c# .net asynchronous task

我有一个服务器,它接受多个客户端请求作为需要从Microsoft Access .mdb数据库文件读取和写入的多个任务。当他们将EnqueueWriteCommand和EnqueueReadCommand作为任务调用时,我想让服务器将它们排队,然后让另一个单独运行的任务(ExecuteTasks)运行排队的任务。这个想法令人费解,但是我似乎找不到或找到更好的方法来做到这一点。这是下面的代码。

从我的测试中,当我调用“ await Task.Run(()=> task)”时,似乎在ExecuteTasks中出现了死锁。

是什么原因导致此僵局?我的总体思路在解决多线程问题时是否正确?有更好的方法吗?

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

}

0 个答案:

没有答案