我试着让标题尽可能具体。基本上我现在在后台工作线程中运行的是一些代码,如下所示:
SqlConnection conn = new SqlConnection(connstring);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(Results);
conn.Close();
sda.Dispose();
其中query是一个字符串,表示一个大的、耗时的查询,conn是连接对象。
我现在的问题是我需要一个停止按钮。我开始意识到杀死后台工作人员将毫无值(value),因为我仍然想保留查询取消后剩下的结果。另外,在查询之后它才能检查取消状态。
到目前为止我想出了什么:
我一直在尝试概念化如何在不对性能造成太大影响的情况下有效地处理这个问题。
我的想法是使用 SqlDataReader 一次从查询部分读取数据,这样我就有一个“循环”来检查我可以通过按钮从 GUI 设置的标志。据我所知,问题是我不能使用数据表的 Load() 方法并且仍然能够取消 sqlcommand。如果我错了,请告诉我,因为这样会更容易取消。
根据我的发现,我意识到如果我做了类似下面的事情(伪代码),我可能只能在查询中取消 sqlcommand:
while(reader.Read())
{
//check flag status
//if it is set to 'kill' fire off the kill thread
//otherwise populate the datatable with what was read
}
但是,在我看来,这将是非常低效的,而且可能代价高昂。这是杀死绝对需要在数据表中的正在进行的 sqlcommand 的唯一方法吗?任何帮助将不胜感激!
最佳答案
确实有两个阶段取消很重要:
根据实际 sql 语句的性质,这两个步骤中的任何一个都可能是 99% 的时间,因此应该同时考虑这两个步骤。例如,在具有十亿行的某个表上调用 SELECT * 基本上不会花费执行的时间,但会花费很长时间读取。相反,在调整不当的表上请求一个 super 复杂的连接,然后将其全部包装在一些聚合子句中可能需要几分钟才能执行,但一旦它们实际返回,读取少数行的时间可以忽略不计。
经过良好调整的高级数据库引擎还会为复杂的查询一次缓存大量的行,因此您会看到引擎正在对下一批行执行查询时交替出现停顿,然后在返回时快速爆发数据下一批结果。
取消查询执行
为了能够在查询执行时取消查询,您可以使用 SqlCommand.BeginExecuteReader 的重载之一。开始查询,然后调用 SqlCommand.Cancel中止它。或者,您可以在一个线程中同步调用 ExecuteReader() 并仍然从另一个线程调用 Cancel()。我没有包括代码示例,因为文档中有很多代码示例。
中止读取操作
这里使用一个简单的 bool 标志可能是最简单的方法。请记住,使用带有对象数组的 Rows.Add() 重载来填充数据表行真的很容易,即:
object[] buffer = new object[reader.FieldCount]
while(reader.Read()) {
if(cancelFlag) break;
reader.GetValues(buffer);
dataTable.Rows.Add(buffer);
}
取消对 Read() 的阻塞调用
如前所述,当调用 reader.Read() 导致数据库引擎执行另一批密集处理时,会出现一种混合情况。如 MSDN 文档中所述,在这种情况下,对 Read() 的调用可能会被阻塞,即使原始查询是使用 BeginExecuteReader 执行的。您仍然可以通过在处理所有读取的一个线程中调用 Read() 而在另一个线程中调用 Cancel() 来解决这个问题。您知道您的阅读器是否处于阻塞的 Read 调用中的方法是在监视线程读取时让另一个标志在阅读器线程更新时:
...
inRead = true
while(reader.Read()) {
inRead = false
...
inRead = true
}
// Somewhere else:
private void foo_onUITimerTick(...) {
status.Text = inRead ? "Waiting for server" : "Reading";
}
关于 Reader 与 Adapter 的性能
DataReader 通常比使用 DataAdapter.Fill() 更快。 DataReader 的全部意义在于能够非常非常快速地响应阅读。即使在数百万行中,每行检查一次 bool 标志也不会增加可测量的时间差异。
大型数据库查询的限制因素不是本地 CPU 处理时间,而是 I/O 管道的大小(远程数据库的网络连接或本地数据库的磁盘速度)或数据库的组合服务器自身的磁盘速度和复杂查询的 CPU 处理时间。 DataAdapter 和 DataReader 都会花费时间(可能是大部分时间)一次等待几纳秒以等待下一行的服务。
DataAdapter.Fill() 的一个便利之处在于,它具有动态生成 DataTable 列以匹配查询结果的神奇功能,但这并不难由您自己完成(参见 SqlDataReader.GetSchemaTable() )。
关于c# - 如何对可以取消的 DataTable 操作执行 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11239625/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack