Thread.Abort不会释放文件

时间:2015-07-10 09:37:39

标签: c# wpf multithreading

我创建了一个在.sqlite中创建数据库的代码,一切正常,但我想确保当用户第一次启动应用程序时必须完成数据库填充。如果用户中止数据库填充,则必须删除数据库(因为应用程序不使用不完整的资源)。现在我已经使用线程来执行创建此数据库的方法,并且我已经在类中声明了线程变量global,如:

Thread t = new Thread(() => Database.createDB());

Database.createDB()方法创建数据库。一切正常,DB正确创建。现在我触发创建数据库的窗口关闭:

protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
            MessageBoxResult result = MessageBox.Show(
                    @"Sure?",
                    "Attention", MessageBoxButton.YesNo, MessageBoxImage.Question);
            try
            {
                if (result == MessageBoxResult.Yes)
                {
                    t.Abort();

                    if (File.Exists("Database.sqlite"))
                    {
                        File.Delete("SoccerForecast.sqlite");
                        Process.GetCurrentProcess().Kill();
                    } ....

事件被触发正确并且线程停止了,但是当条件开始if (File.Exists("Database.sqlite"))时,编译器告诉我:

  

无法删除文件 - 使用其他进程。

但是我已经停止了线程,为什么会出现此异常?我做错了什么?

更新:

在CreateDb()方法中,我也调用了不同类的其他方法,其中一个具有如下结构:

public void setSoccer()
{
        Database.m_dbConnection.Open(); 
        string requestUrl = "...";
        string responseText = Parser.Request(requestUrl);
        List<SoccerSeason.RootObject> obj = JsonConvert.DeserializeObject<List<SoccerSeason.RootObject>>(responseText);

        foreach (var championships in obj)
        {
            string sql = "string content";
            SQLiteCommand command = new SQLiteCommand(sql, Database.m_dbConnection);
            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        string query = "select * from SoccerSeason";
        SQLiteCommand input = new SQLiteCommand(query, Database.m_dbConnection);
        SQLiteDataReader reader = input.ExecuteReader();

        int i = 0;
        while (reader.Read())
        {
            //reading data previously inserted in the database
        }
        Database.m_dbConnection.Close(); /
}

我想知道我应该在哪里放置标志变量,因为这段代码里面有不同的循环。

1 个答案:

答案 0 :(得分:1)

当你中断线程时,它可能没有干净地关闭数据库连接,因此你会看到错误。

我可能会建议进行轻微的重新设计,因为using Thread.Abort is not ideal 而是使用变量作为取消标志来通知线程关闭 然后,当线程检测到设置了此取消标志时,它可以正确关闭连接并处理数据库删除本身。

更新
一个简短的例子来说明我的意思;它不是很漂亮,它不会编译,但它提供了一般的想法。

public class Database
{
    public volatile bool Stop= false;

    public void CreateDb()
    {
        if(!Stop)
        {
           // Create database 
        }

        if(!Stop)
        {
           // Open database
           // Do stuff with database
        }

        // blah blah ...

        if(Stop)
        {
           // Close your connections
           // Delete your database
        }
    }
}

...

    protected override void OnClosing(CancelEventArgs e)
    {
        Database.Stop = true;
    }

现在你已经大致了解了你正在寻找的东西我衷心地推荐谷歌搜索关于线程取消的帖子,知道他们正在谈论什么的人可以告诉你如何正确地做到这一点。

这些可能是合理的起点:
How to: Create and Terminate Threads
.NET 4.0+实际上有一个CancellationToken对象,考虑到这个目的Cancellation in Managed Threads