-1

I have a code and I need a delay but I'm working in NET. 3.5 and I can't use Thread.Sleep because the whole program doesn't respond. Are there any alternatives? I'm using C# and WinForms. Thats my code where I want to add the delay:

private async void Form6_Load(object sender, EventArgs e)
{
    serialPort.ReceivedBytesThreshold = 1;
    serialPort.ReadTimeout = 10000;
    serialPort.WriteTimeout = 10000;
    serialPort.Open();
    serialPort.DtrEnable = true;
    serialPort.RtsEnable = true;
    label1.Visible = true;
    Thread.Sleep(3000);
    label1.Visible = false;
    label2.Visible = true;
    serialPort.WriteLine("ATD");
    serialPort.Write(Environment.NewLine);
    serialPort.ReadLine();
    Thread.Sleep(10000);
    serialPort.Close();
    Thread.Sleep(2000);
    serialPort.Open();
    serialPort.WriteLine("ATA");
    serialPort.Write(Environment.NewLine);
    serialPort.ReadLine();
    Thread.Sleep(20000);
    serialPort.Close();
}
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
  • Going to need more than that. WHAT kind of app are you making here?... – Idle_Mind Jun 08 '22 at 14:59
  • I wrote it now in the post :) Sorry about that – oldwebrebirthproject1980 Jun 08 '22 at 15:02
  • First-off, what exactly do you mean by ".NET 3.x"? – Dai Jun 08 '22 at 15:05
  • https://stackoverflow.com/a/35855885/11683? – GSerg Jun 08 '22 at 15:06
  • If you mean .NET Framework 3.X, then the correct solution would be to [use a BackgroundWorker](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-implement-a-form-that-uses-a-background-operation). – Yarik Jun 08 '22 at 15:07
  • 1
    Where-and-how are you even running .NET Framework 3.5? Every supported platform for .NET Fx 3.5 supports .NET Fx 4.8, so why not just update the application instead? – Dai Jun 08 '22 at 15:08
  • @Yarik How can `BackgroundWorker` be used as a non-blocking millisecond-precision alternative to `Task.Delay`? – Dai Jun 08 '22 at 15:10
  • If WinForms, you could drop a Timer control on your form and use the Tick() event. – Idle_Mind Jun 08 '22 at 15:11
  • @Dai, you put your whole method with delays into the `DoWork` event handler, and use `ReportProgress` to update the UI such as your labels. – Yarik Jun 08 '22 at 15:13
  • 4
    I noticed that the method is `Form6_Load` - which means you've got at least 5 other `Form` classes in your project that are still using their unhelpfully undescriptive default names `Form1` through `Form6` - why is it that so many people simply never give their objects and types _good names_? _le sigh...) – Dai Jun 08 '22 at 15:13
  • @Yarik That's not non-blocking though... – Dai Jun 08 '22 at 15:14
  • @Dai, I'm not sure what do you mean by "not non-blocking" since `DoWork` runs on background thread. – Yarik Jun 08 '22 at 15:17
  • if you want to move your code to background worker [such as threadpool] - you need to handle on the main thread [beginInvoke] all UI work. – ephraim Jun 08 '22 at 15:19

2 Answers2

1

If we go back to the .NET Framework 3.5 ways to do things, then the most widely used solution would be to use a BackgroundWorker, which is just a handy wrapper around ThreadPool.QueueUserWorkItem.

What you do is you drop BackgroundWorker onto your form, subscribe to the DoWork event, and move your serial port logic there. If you need to access any UI controls, you either use BackgroundWorker.ReportProgress, or, even better, Control.Invoke as shown below.

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    serialPort.ReceivedBytesThreshold = 1;
    serialPort.ReadTimeout = 10000;
    serialPort.WriteTimeout = 10000;
    serialPort.Open();
    serialPort.DtrEnable = true;
    serialPort.RtsEnable = true;
    Invoke(new Action(() => label1.Visible = true));
    Thread.Sleep(3000);
    Invoke(new Action(() => label1.Visible = false));
    Invoke(new Action(() => label2.Visible = true));
    serialPort.WriteLine("ATD");
    serialPort.Write(Environment.NewLine);
    serialPort.ReadLine();
    Thread.Sleep(10000);
    serialPort.Close();
    Thread.Sleep(2000);
    serialPort.Open();
    serialPort.WriteLine("ATA");
    serialPort.Write(Environment.NewLine);
    serialPort.ReadLine();
    Thread.Sleep(20000);
    serialPort.Close();
}

But of course, I would highly recommend to update your project to .NET Framework 4.5 (at least), and use async/await with Task.Delay.

Yarik
  • 1,423
  • 1
  • 14
  • 16
-1

Since you mention you work with .Net 3.5 you cannot use Tasks. Use Threadpool instead.

ThreadPool.QueueUserWorkItem(doJob, null);
private static void doJob(object obj)
{
     Thread.Sleep(1000);
     //do your job here
}
mxmissile
  • 11,464
  • 3
  • 53
  • 79
ephraim
  • 379
  • 1
  • 3
  • 15
  • 2
    If you're using the threadpool then **don't** block those threads either by using `Thread.Sleep` - instead you should yield the thread back to the pool (like what `await` does, but without the benefit of the `await` keyword) and request a continuation using a `System.Threading.Timer` or `System.Timers.Timer` (depending on your requirements) – Dai Jun 08 '22 at 15:12
  • I like your comment. But it looks as if ht need the most simple solution...he just wants to open a serial port... – ephraim Jun 08 '22 at 15:14
  • 1
    They're doing more than just opening a serial-port, they're attempting some kind of interactive and almost-real-time user-interface for it - whatever the OP's doing I'm getting the impression it's nontrivial. – Dai Jun 08 '22 at 15:16
  • I'm attempting to dial my Dial-Up modem and on my UI it should show something like label1 when the ATD Command is executed :) – oldwebrebirthproject1980 Jun 08 '22 at 16:16