C#: 是否可以取消Linq2Sql查询?

5

是否可以取消linq2sql查询?比如我已经构建了一个需要运行一段时间的查询,我希望用户可以取消它。有没有任何好的想法?

4个回答

2
如果您设置DataContextCommandTimeout(秒)属性,当超时时间到达后,它将自动抛出异常。请注意保留HTML标签。

1
但是你能在查询运行时设置它吗? - Svish
不可以-你应该在命令开始之前设置它。我不确定在查询运行时更改它的定义行为是什么。 - Richard Szalay
是的,但我不想在随机时间终止查询。我希望在用户要求停止时终止它。 - Svish
你最好在后台线程中运行查询,并在用户点击取消时简单地取消订阅容器对象的事件。 - Richard Szalay
那就算了,让它在后台完成? - Svish
显示剩余2条评论

2
所以,根据Richard Szalay的评论:

你最好在后台线程中运行查询,当用户点击取消时,从容器对象的事件中简单地取消订阅。

我认为我同意这是一个可以接受的解决方法。我希望能够看到一些异步查询功能已经集成在框架中,但在这种情况下,我们只能这样做。
我还没有开始实现它(必须先完成其他一些事情),但它可以按照以下方式工作:
  • 在工作线程中,在单独的查询线程中执行查询,然后加入该线程,直到它完成。
  • 当用户点击取消时,调用工作线程的Interrupt方法,然后会收到ThreadInterruptedException并停止等待查询线程的完成。

后面我可能会添加一些代码,让它更完美。

我不建议使用这种解决方案。使用ThreadInterruptedException和使用Thread.Abort一样糟糕。我建议阅读我在Kieron答案评论中发布的文章。 - Richard Szalay
也许可以进入一个循环并检查标志或其他内容,然后如果用户想要取消,则直接返回而不等待结果? - Svish

0

我知道这个答案有点晚,但这是我实现它的方式:

class Program
{        
    public class Person
    {
        public string Name;
        public int Age;
    }        

    public static void ExecuteQueryAsync ( IEnumerable<Person> collectionToQuery , Action<List<Person>> onQueryTerminated , out Action stopExecutionOfQuery )
    {
        var abort = false;

        stopExecutionOfQuery = () =>
        {
            abort = true;
        };            

        Task.Factory.StartNew( () =>
        {
            try
            {
                var query = collectionToQuery.Where( x =>
                {
                    if ( abort )
                        throw new NotImplementedException( "Query aborted" );

                    // query logic:
                    if ( x.Age < 25 )
                        return true;
                    return
                        false;
                } );

                onQueryTerminated( query.ToList() );

            }
            catch
            {
                onQueryTerminated( null );
            }
        });
    }


    static void Main ( string[] args )
    {
        Random random = new Random();

        Person[] people = new Person[ 1000000 ];

        // populate array
        for ( var i = 0 ; i < people.Length ; i++ )
            people[ i ] = new Person() { Age = random.Next( 0 , 100 ) };

        Action abortQuery;
        ExecuteQueryAsync( people , OnQueryDone , out abortQuery );

        // if after some time user wants to stop query:
        abortQuery();

        Console.Read();
    }

    static void OnQueryDone ( List<Person> results )
    {
        if ( results == null )
            Console.WriteLine( "Query was canceled by the user" );
        else
            Console.WriteLine( "Query yield " + results.Count + " results" );
    }
}

-1
我会建议你在一个单独的线程上运行它,然后取消该线程。

我不建议走这条路。使用Thread.Abort是一种不良的实践,甚至不能保证中止线程。请参阅http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx。 - Richard Szalay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接