这是对WinForms RichTextBox的跟进
:如何在TextChanged上执行格式化?
我有一个带有RichTextBox的Winforms应用程序,该应用程序会自动突出显示所述框的内容.因为大型文档的格式化需要很长时间,10秒或更长时间,我已经设置了BackgroundWorker来重新格式化RichTextBox.它遍历文本并执行一系列这些:
rtb.Select(start, length);
rtb.SelectionColor = color;
Run Code Online (Sandbox Code Playgroud)
在这样做的同时,UI仍然保持响应.
BackgroundWorker从TextChanged事件开始.像这样:
private ManualResetEvent wantFormat = new ManualResetEvent(false);
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
xpathDoc = null;
nav = null;
_lastChangeInText = System.DateTime.Now;
if (this.richTextBox1.Text.Length == 0) return;
wantFormat.Set();
}
Run Code Online (Sandbox Code Playgroud)
后台worker方法如下所示:
private void DoBackgroundColorizing(object sender, DoWorkEventArgs e)
{
do
{
wantFormat.WaitOne();
wantFormat.Reset();
while (moreToRead())
{
rtb.Invoke(new Action<int,int,Color>(this.SetTextColor,
new object[] { start, length, color} ) ;
}
} while (true);
}
private void SetTextColor(int start, int length, System.Drawing.Color color) …Run Code Online (Sandbox Code Playgroud) 我对我正在使用的 ManualResetEvent 似乎没有解除阻塞感到有些困惑。有谁知道为什么会这样?
我的情况是这样的。实际情况非常复杂,我没有设法隔离一段合理的代码来重现问题。
编辑
我已经更新了下面的代码示例。这是在许多不同的对话框中执行的,我注意到其中一个点击了 this.mre.WaitOne(); 然后发生的是我得到一个“服务器忙”对话框,在那里我需要按“切换到”或“重试”,然后我的代码将允许我的代码单步通过 WaitOne() 调用,一切都会起作用。我不确定它的相关性,但显然它有些重要。
public class A
{
ManualResetEvent mre;
public void Start(ThreadClass tc)
{
this.mre = new ManualResetEvent(false);
tc.Begin();
WebClient wc = new WebClient();
// progress events are pumped to the ThreadClass which then update the Form2.
wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync("Src", "Tgt");
this.mre.WaitOne();
}
void void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
try
{
// Do Stuff
}
finally
{
this.mre.Set();
}
}
}
public class ThreadClass
{
Begin()
{
Thread t = …Run Code Online (Sandbox Code Playgroud) 我已经编写了我希望在C#/ .NET中使用ManualResetEvent和AutoResetEvent类的轻量级替代方法.这背后的原因是让事件像功能一样没有使用内核锁定对象的重量.
尽管代码似乎在测试和生产中都运行良好,但是对于所有可能性来说,这种方法都是正确的,这可能是一件令人担忧的事情.我会谦卑地请求StackOverflow人群对此提出任何建设性意见和批评.希望(经过审核)这对其他人有用.
用法应类似于Manual/AutoResetEvent类,其中Notify()用于Set().
开始:
using System;
using System.Threading;
public class Signal
{
private readonly object _lock = new object();
private readonly bool _autoResetSignal;
private bool _notified;
public Signal()
: this(false, false)
{
}
public Signal(bool initialState, bool autoReset)
{
_autoResetSignal = autoReset;
_notified = initialState;
}
public virtual void Notify()
{
lock (_lock)
{
// first time?
if (!_notified)
{
// set the flag
_notified = true;
// unblock a thread which is waiting on this signal
Monitor.Pulse(_lock);
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试利用MSDN的异步客户端套接字代码示例来连接和控制一些家用设备.据我所知,示例代码的ReceiveCallback方法使用EventWaitHandle ManualResetEvent的实例和方法receiveDone.WaitOne()来保存当前线程的处理,直到线程收到一个信号表明所有套接字的数据都已从远程设备传输.在传输完所有套接字数据后(套接字的数据为空且bytesRead = 0),删除了Waithandle并继续处理应用程序.
不幸的是,通过逐步执行代码,似乎在客户端最后一次从远程设备返回数据之后,ReceiveCallback永远不会返回以查看数据队列是否为空(即bytesRead = 0),因此永远不会在ReceiveCallback中输入"else"条件,其中ManualResetEvent的状态将被重置并且应用程序将继续处理.因此,由于它永远不会进入"else"状态,因此永远不会重置ManualResetEvent并且应用程序会冻结.
虽然我可以从代码中删除"receiveDone.WaitOne()"方法 - 允许执行而不等待ManualResetEvent通知已收到所有数据; 这将返回设备中通常不完整的数据字符串.
我是否错误地使用此代码示例?有没有人见过这个或者有过如何解决这个问题的经验?
7/14/2012 - 更新:在进一步测试MSDN的异步客户端套接字示例后,很明显ReceiveCallback实际上重新轮询端口,并且只有在套接字被释放时才满足"bytesRead = 0"条件(即客户端. Shutdown(SocketShutdown.Both); client.Close();).如果我理解正确,这意味着必须关闭连接以通过receiveDone.WaitOne()方法.如果关闭连接以满足WaitOne()Waithandle,它完全违背了应用程序的目的,因为我一直希望保持连接打开,以便应用程序可以监听设备更新,这种情况不断发生.
2012年7月16日 - 更新:我写信给微软技术支持部门,他们回复说"我们正在研究这个问题.我们可能需要一些时间才能回复你." 因此,似乎此时通过按摩此代码似乎无法解决此挑战.
如果没有Asynchronous Client Socket示例代码作为编写异步通信程序的基础,请问是否有人可以建议更可靠的替换例程? 有三个设备,每个设备都有自己的IP地址和端口号.因此,如果可以使用类,可以为每个设备创建实例,这将是理想的.此外,端口必须保持打开状态,以接收设备不断发送的自发更新.最后,更新没有结束字符或定义长度信令消息的传输完成,因此例程必须不断地轮询端口以获取可用数据. 任何建议或意见将不胜感激.
2012年7月18日 - 解决方法:在花费大量时间尝试使MSDN的异步客户端套接字代码示例正常工作之后,很明显我必须在其他地方查找以获得程序持续识别的设备响应.为了拯救别人的脑损伤,我已经包含了我使用的解决方案,这似乎在这一点上运作良好.如果有人有任何建议,请不要犹豫,加入这个问题!
//
// ORIGINAL CODE ATTEMPT
//
public static Socket LutronClient; …Run Code Online (Sandbox Code Playgroud) Windows允许创建(命名)事件对象.
一个事件(Windows中的同步原语)可以是自动重置类型(在这种情况下你可以说它是一种信号量)或者它可以是手动重置类型,在这种情况下它会保持设置直到有人重置它.
现在,从文档的CreateEvent,OpenEvent,SetEvent的,等它似乎是没有办法确定,一旦事件已经创建,无论是自动复位或maual复位.
我处于这种情况,其中一个进程创建一个命名的事件,第二个进程必须对此事件进行操作(它将传递名称,然后打开事件并最终发出信号).由于事件应始终是手动重置事件,因为整个事情都有意义,我本来希望在第二个过程中添加一个检查以确保它是一个手动重置事件.有没有办法检查这个?
(是的,在我的情况下,它更像是一个很好的东西,因为如果任何代码创建一个自动重置事件然后将它传递给这个过程,那么它将是一个错误.但是错误发生了,如果发生了错误,那就更好了.我可以发现它们.)
windows winapi manualresetevent autoresetevent windows-kernel
我正在使用一个使用ManualResetEvent同步线程的应用程序.FxCop告诉我处理这些物品.我发现以下讨论告诉了我同样的事情:
我需要Dispose()或Close()一个EventWaitHandle吗?
但我不知道何时处理ManualResetEvent的实例.
以下简化代码演示了此问题:
private void btn_Click(object sender, EventArgs e)
{
var mre = new ManualResetEvent(false);
new Thread(() => this.SetEvent(mre)).Start();
for (int i = 0; i < 10; ++i)
{
new Thread(() => this.WaitFor(mre)).Start();
}
}
private void SetEvent(ManualResetEvent manualResetEvent)
{
Thread.Sleep(10000);
manualResetEvent.Set();
}
private void WaitFor(ManualResetEvent manualResetEvent)
{
manualResetEvent.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)
问题是存在多个ManualResetEvent实例,并且多个线程正在等待每个实例.
如果我记住列表中的实例,我不知道何时处理它.在WaitOne()之后处理它 - 调用将多次处理它,并且可能在其他线程仍在等待时处理它.
创建事件的线程没有任何对它的引用.setter-thread不应该处置它,因为还有其他线程在等待这个MRE.每个等待的线程都无法像前面提到的那样处理它.
所以问题是:什么时候应该处理这个ManualResetEvent?
我在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)我正在尝试使用ManualResetEventSlim该类在几个并行任务之间进行通信。
这是代码的简化版本:
class Program
{
private static void Main(string[] args)
{
Stopwatch stopwatch = Stopwatch.StartNew();
ManualResetEventSlim eventSlim = new ManualResetEventSlim(false);
Task.Run(() =>
{
Task.Run(() =>
{
Thread.Sleep(1000);
eventSlim.Set();
});
eventSlim.Wait();
Console.WriteLine($"Hello from the Task! {stopwatch.Elapsed}");
});
eventSlim.Wait();
Console.WriteLine($"Hello from the Main thread! {stopwatch.Elapsed}");
stopwatch.Stop();
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
大多数情况下,代码运行良好并输出:
Hello from main thread! 00:00:01.1017591
Hello from task! 00:00:01.1017630
Run Code Online (Sandbox Code Playgroud)
但是,每五六次运行一次代码,我只会得到以下输出:
Hello from main thread! 00:00:01.1017591
Run Code Online (Sandbox Code Playgroud)
而WaitTask 内部之后的代码永远不会被调用。
我使用.NET Core 2.0.2上Windows Server 2012 R2有Visual …
我有一个长时间运行的进程将数据发送到另一台机器。但是这些数据是分块接收的(比如一组 100 个数据包,然后延迟至少 10 秒)。
我在一个单独的线程上启动了发送功能
Task.Run(() => { SendPackets(); });
要发送的数据包Queue<Packet>由某个其他功能在一个对象中排队。
在SendPackets()我使用 while 循环来检索和发送(异步)队列中的所有可用项目。
void SendPackets()
{
while(isRunning)
{
while(thePacketQueue.Count > 0)
{
Packet pkt = thePacketQueue.Dequeue();
BeginSend(pkt, callback); // Actual code to send data over asynchronously
}
Task.Delay(1000); // <---- My question lies here
}
}
Run Code Online (Sandbox Code Playgroud)
所有的锁都到位了!
我的问题是,当我使用 时Task.Delay,下一个循环是否可能由与当前循环不同的线程执行?
有没有其他方法,而不是指定 1 秒的延迟,我可以使用类似的东西ManualResetEvent,以及相应的代码是什么(我不知道如何使用ManualResetEvent等。
另外,我是 async/await 和 TPL 的新手,所以请容忍我的无知。
TIA。
c# asynchronous manualresetevent task-parallel-library async-await
对于第一次调用,下面的方法应返回true,对于任何其他调用,返回false.
它有什么问题吗?使用重置事件进行锁定是否安全?
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
public bool AmIFirst()
{
lock (_resetEvent)
{
bool first = !_resetEvent.WaitOne(0);
if (first)
_resetEvent.Set();
return first;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在评论你的评论后做了一些修改.ManualResetEvent由于以前的设计理念,我被困住了.其实我根本不需要它.
class ActionSynchronizer
{
private Timer _expirationTimer;
private object _locker = new object();
private bool _executionRequired = true;
private SomeDelegate _onExpired = delegate { };
public ActionSynchronizer(SomeDelegate onExpired)
{
_onExpired = onExpired;
expirationTimer = new Timer(OnExpired, null, 30000, Timeout.Infinite);
}
public bool IsExecutionRequired()
{
if (!_executionRequired)
return false;
lock (_locker)
{ …Run Code Online (Sandbox Code Playgroud) manualresetevent ×10
c# ×7
.net ×4
asynchronous ×2
.net-core ×1
async-await ×1
client ×1
deadlock ×1
idisposable ×1
richtextbox ×1
sockets ×1
task ×1
winapi ×1
windows ×1
winforms ×1