c# - 如何正确允许多个任务访问数据库文件?
问题描述
我有一个服务器,它接受多个客户端请求作为需要从 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;
}
}
}
解决方案
推荐阅读
- javascript - 如何区分绑定到输入元素的数据列表的选择、更改、输入和粘贴事件
- ruby-on-rails - rails匹配params中字符串的结尾
- apache-kafka - Kubernetes 上的 Kafka - UNKNOWN_TOPIC_OR_PARTITION 和 LEADER_NOT_AVAILABLE 错误
- entity-framework - 脚手架错误 Microsoft.EntityFramework
- php - 如何在 youtube codgiter 上上传视频?
- jpa - 在 localdate 列中添加天数
- scala - 用于理解地图操作结果的 Scala 将作为 Int 出现
- c - GCC 输出空的汇编文件
- php - Parsing a Multi Dimensional JSON string from URL
- python - 为什么元素的形状和逻辑索引数组似乎会转置维度?