我有C#多线程的问题.
表格内容是两个按钮和两个标签.
如果我按下第一个按钮,从1..00到60000循环,更新label1.(它的工作原理)
如果我按下第二个按钮,从1..6到6000循环更新label2,(我的表格滞后).(没有回应)
请帮忙!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(countNumbers));
thread.IsBackground = true;
thread.Start();
}
private void button2_Click(object sender, EventArgs e)
{
Thread thread2 = new Thread(new ThreadStart(countNumbers2));
thread2.Start();
}
public void countNumbers()
{
try
{
for …Run Code Online (Sandbox Code Playgroud) 可能重复:
如何在后台线程运行时阻止Winforms UI
我正在使用C#WinForm应用程序
我在屏幕上有一个Save按钮,屏幕数据保存到数据库中.
当用户点击按钮应用程序进入数据库并保存数据时会发生什么.这需要一些时间.
但是,如果用户再次单击"保存"按钮,则会触发Click事件,当第一次单击返回主代码(保存数据库后)时,捕获的事件将被触发.
简而言之,当线程从第一个事件返回时,会捕获并触发click事件(我尝试了启用/禁用按钮的方案).
我怎样才能阻止这种行为.
此致,Akhil
@Jalal:我尝试了一些修改后的代码
private readonly object _userActivityLocker = new object();
private void btnSave_Click(object sender, EventArgs e)
{
if (System.Threading.Monitor.TryEnter(_userActivityLocker))
{
//note that any sub clicks will be ignored while we are here
try
{
DateTime dt = DateTime.Now;
Thread.Sleep(2000);
Debug.Print("FirstClick {0} Second Click {1}",dt.ToLongTimeString(), DateTime.Now.ToLongTimeString());
//here it is safe to call the save and you can disable the btn
Application.DoEvents();
}
finally
{
System.Threading.Monitor.Exit(_userActivityLocker);
//re-enable the btn if you disable it.
} …Run Code Online (Sandbox Code Playgroud) 我正在开发一个基于webBrowser控件的消息传递系统,这样我就可以格式化文本了.当用户离线并发送消息时,将存储消息并在重新登录时为每条消息发送事件.当我为网站设置默认html等时,我通常使用:
while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
Run Code Online (Sandbox Code Playgroud)
这在程序正常运行时有效.当用户正在接收他们离线时发送的消息时,这将触发下一个消息事件,依此类推,每个消息一直到最后一个消息.这意味着它们脱机时发送的最后一条消息是唯一显示的消息.我想像Application.DoEvents()这样的东西允许控件不断更新和加载,但这不会触发其他事件.
谢谢
编辑:
我通过完全删除DoEvents()来解决问题.我没有像我工作那样更改DocumentText,而是设置了一个字符串构建器,然后在最后设置html all.
我在C#-Program中遇到了WebBrowsing自动化的问题.我之前使用过代码来获取BHO,并且它正在运行.但在纯粹的c#程序中,似乎存在某种僵局.我已经指示我的程序点击搜索按钮,然后等待(通过手动重新发送)文档完成信号.但是现在似乎在ManualResetEvent发出超时信号之前不会处理点击搜索按钮.然后单击,并且还会触发DocumentComplete-Event.
对于该程序的结构:WebBrowser-Control是WindowsForm的一部分.WebBrowser控件传递给运行Thread的Class.该类再次将控件传递给另一个类,其中根据加载的webbrowser编程具体行为.
所以在Code中这样看起来:
线程的设置
_runner = new Thread(runner);
_runner.SetApartmentState(ApartmentState.STA);
_runner.IsBackground = true;
_runner.Start();
Run Code Online (Sandbox Code Playgroud)用流道法加工
b.placeTipp(workStructure);
Run Code Online (Sandbox Code Playgroud)PlaceTipp方法
public void placeTipp(ref OverallTippStructure tipp)
{
_expectedUrl = String.Empty;
_betUrl = String.Empty;
_status = BookieStatusType.CHECKLOGIN;
while (true)
{
_mreWaitForAction.Reset();
checkIETab();
switch (_status)
{
case BookieStatusType.REQUESTWEBSITE:
ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Keine IE-Tab vorhanden. Fordere eine an", this.BookieName));
//if (RequestIETabEvent != null)
// RequestIETabEvent(this, new EventArgs());
_status = BookieStatusType.NAVIGATETOWEBSITE;
_mreWaitForAction.Set();
break;
case BookieStatusType.NAVIGATETOWEBSITE:
_webBrowser.Navigate(@"http://www.nordicbet.com");
break;
case BookieStatusType.CHECKLOGIN:
checkLogin();
break;
case BookieStatusType.LOGINNEEDED:
doLogin();
break;
case BookieStatusType.LOGGEDIN:
_status = BookieStatusType.SEARCHTIPP; …Run Code Online (Sandbox Code Playgroud)解决方案后添加的注意事项:反射调用的方法内部抛出了AccessViolationException.这是无法捕获TargetInvocationException的原因.
注意:这是IDE的外部. 引用的问题不一样.
TL; DR
如何通过其他方式获取异常或获取所需信息?
详细描述:
我遇到的问题是在一个被反射调用的方法中发生的异常.异常本身实际上发生在被调用的方法中,但由于该方法是通过反射调用的,因此真正的异常包含在a中System.Reflection.TargetInvocationException.没问题,只需抓住它并获得内部异常 - 除了System.Reflection.TargetInvocationException没有被抓住.我的程序崩溃,我得到一个转储以及Windows事件日志中的条目.
Windows事件日志不包含内部异常,也不包含转储.我无法将调试器附加到程序,因为然后外部库(需要进入反射调用)将无法运行 - 复制保护,你不知道.如果我将一个try/catch放入有问题的方法中,则不会发生异常 - 这很糟糕.原因不是固定的,它不会再发生了.如果我将登录放入有问题的方法,则会发生同样的效果 - 不再发生异常.
我不能使用日志记录,我不能使用调试器,并且在我可以捕获异常并记录它的一个地方,异常不会被捕获.
我正在使用Visual Studio 2010和dotnet 4.0.
为了说清楚:当程序在Visual Studio之外运行时,try/catch不起作用,我无法在调试器中的Visual Studio内运行它,因为那时程序无法到达异常点发生.这不在IDE中.
消除反射不是一种选择(我只针对一种情况尝试过,异常就消失了.)
被调用的方法做了很多事情,但将其分解为更小的方法并没有帮助 - 例外情况就消失了.
该异常不会一直发生,只有当我执行某一系列步骤时 - 并且当它发生时,它总是在整个序列中第二次发生.
在我使用的序列中,该方法几乎同时由两个线程调用 - 输入一组特定的数据,这导致报告的副本和另一个文档打印在两个单独的打印机上 - 每个打印机一个报告和文档.由于生成报告和打印文档可能需要一段时间,因此它们在后台的线程上完成,因此用户可以继续工作.
我怀疑线程正在踩着彼此的脚趾(正在进行大量的文件和数据库操作),但不知道实际发生了什么,我无法修复它.
下面的代码显示了通过反射调用的简化版本.
是否有人建议可能导致System.Reflection.TargetInvocationException不被捕获的原因,或者可能是另一种捕获内部异常的方法?
Try
Dim methode As System.Reflection.MethodInfo
methode = GetType(AParticularClass).GetMethod("OneOfManyMethods", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static)
Dim resultobject As Object = methode.Invoke(Nothing, Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static, Nothing, New Object() {SomeBooleanVariable, SomeStringVariable}, Nothing) …Run Code Online (Sandbox Code Playgroud) 我想阻止按钮点击排队.在测试中,我有一个Form,一个Button,在Code-Behind中我有事件处理程序:
private void button1_Click(object sender, EventArgs e)
{
if (_codeRunning)
return;
_codeRunning = true;
//Application.DoEvents();
//button1.Enabled = false;
_click ++;
Debug.WriteLine("Click Number: " + _click);
Task.Delay(5000).Wait();
//button1.Enabled = true;
_codeRunning = false;
}
Run Code Online (Sandbox Code Playgroud)
当我运行调试并快速单击按钮两次或三次或四次时,"调试输出"会在最后一次显示后大约五秒钟显示每次单击.我希望它显示的是单击并删除其余部分,直到第一个事件完成.
我还尝试禁用该按钮,以及暂时从Button_click事件中删除Handler.结果都是一样的.
Start-Job我创建了一个 Windows 表单,您可以在其中单击一个按钮来启动大约 15 分钟的备份过程(使用)。我使用它是Start-Job为了在备份过程中保持表单响应(响应式我的意思是你可以移动它,最小化它等等)。但是,我希望表单在工作完成后弹出一个消息框,但我无法获得正确的结果。
首先,我尝试了一个While循环,每 10 秒检查一次作业是否完成:
$BackupButton.Add_Click( {
$BackupJob = Start-Job -ScriptBlock { ... }
$Completed = $false
while (!($Completed)) {
if ($BackupJob.State -ne "Running") {
$Completed = $true
}
Start-Sleep -Seconds 10
}
[System.Windows.Forms.MessageBox]::Show('Successfully completed the backup process.', 'Backup Tool', 'OK', 'Info')
})
Run Code Online (Sandbox Code Playgroud)
这在作业完成后给了我一个消息框,但表单在此过程中没有响应,可能是因为它仍在循环中使用线程的资源While。
然后,我尝试使用Register-ObjectEvent调用消息框来显示作业状态何时更改:
$BackupButton.Add_Click( {
$BackupJob = Start-Job -ScriptBlock { ... }
Register-ObjectEvent $BackupJob StateChanged -Action {
[System.Windows.Forms.MessageBox]::Show('Successfully completed the backup process.', 'Backup Tool', 'OK', 'Info') …Run Code Online (Sandbox Code Playgroud) 我正在尝试将一些代码移动到某些类文件中以清理我的代码.我遇到问题的一个方面是报告执行任务的对象和进度条之间事件的进度.
我想事件函数必须放在新类中,但是他们还需要更新调用表单上的进度条?class\object可以代替事件处理程序返回更新吗?
目前表单包含所有代码:
Function DoRestore(ByVal SQLServer As String, ByVal BackupFilePath As String, ByVal DatabaseName As String)
Dim Server As Server = New Server(SQLServer)
Server.ConnectionContext.ApplicationName = Application.ProductName
Dim res As Restore = New Restore()
Dim dt As DataTable
res.Devices.AddDevice(BackupFilePath, DeviceType.File)
dt = res.ReadFileList(Server)
res.Database = DatabaseName
res.PercentCompleteNotification = 1
AddHandler res.PercentComplete, AddressOf RestoreProgressEventHandler
AddHandler res.Complete, AddressOf RestoreCompleteEventHandler
res.SqlRestoreAsync(Server)
While res.AsyncStatus.ExecutionStatus = ExecutionStatus.InProgress
Application.DoEvents()
End While
End Function
Private Function RestoreProgressEventHandler(ByVal sender As Object, ByVal e As PercentCompleteEventArgs)
'Update progress bar (e.Percent) …Run Code Online (Sandbox Code Playgroud) 我正在使用Visual C#sand我使用的是Windows窗体而不是控制台应用程序.因此,我不是在Main()中工作,而是在Form File中工作.我对C#也很陌生,所以如果我的一些问题是愚蠢的,那就很抱歉.
我基本上需要做的是当我的程序启动时我需要它来永远循环.因为我没有Main(),所以我会把这段代码放在哪里?我把它放在有InitializeComponent()的函数中吗?我需要在程序启动后立即启动循环.但是,我需要在循环之前首先声明一些变量.所以基本上我需要声明变量然后开始无限循环.变量是全球性的.
其次,当用户按下按钮时,我需要无限循环中断.我该怎么做?我在考虑以下几点:
while (buttonIsPressed == false)
{
//do whatever I need to do
}
Run Code Online (Sandbox Code Playgroud)
但是,我意识到按钮的功能永远不会被调用,因为我被困在那个循环中.如果由于处于无限循环中而从未到达按钮的功能,我无法从按钮的功能设置变量.有任何想法吗?我在思考线程,但我对线程没有任何经验,所以我有点不愿意尝试它.
聊天应用程序.程序启动时我需要它继续听.但是,当用户单击"连接"时,它会停止侦听,而是启动连接
我正在创建一个聊天客户端.所以基本上当我的程序启动时,我需要它继续听.但是,当用户单击"连接"时,它需要停止侦听,而是启动连接
我想启动一个侦听事件并在后台处理它们的线程.这是我到目前为止所做的:
private Thread mThread;
private bool mKeepHandlingIt;
private void Init()
{
mKeepHandlingIt = true;
mThread = new Thread(ProcessEvents);
mThread.SetApartmentState(ApartmentState.STA);
mThread.Start();
}
private void ProcessEvents()
{
StaticClass.CoolEvent += HandleIt;
StaticClass.StartDoingStuff();
while (mKeepHandlingIt)
{
Application.DoEvents();
}
StaticClass.StopDoingStuff();
StaticClass.CoolEvent -= HandleIt;
}
private void HandleIt(object sender, EventArgs e)
{
//Handles it
}
protected override void Dispose()
{
if (mThread != null)
{
mKeepHandlingIt = false;
mThread.Join();
}
}
Run Code Online (Sandbox Code Playgroud)
有更好的方法吗?就像一个更适合这个目的的线程类?在这种情况下,BackgroundWorker似乎不是更好的选择......
如果这是一个很好的方法,那么我有一个我无法理解的问题.上面的解决方案适用于侦听事件和处理它们,但是当调用Dispose并且mKeepHandlingIt设置为false时,退出while循环(如果我在循环中放置断点,调试器不会中断)但是后面没有代码执行循环并且mThread.Join永远不会返回.基本上......我想知道的是:如何停止线程,然后确保在清理之前不要继续?