Reputation: 165
I have a form load splash screen, which contains a small gif image. Recently it start trowing an exception saying " Thread was being aborted" when it tries to load the main form. This is the Exception
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI(HandleRef graphics, HandleRef image, Int32 x, Int32 y, Int32 width, Int32 height)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
This is what i've got on the splash form
public partial class Loading_Screen : Form
{
public Action worker { get; set; }
public Loading_Screen(Action worker)
{
InitializeComponent();
if (worker == null)
throw new ArgumentOutOfRangeException();
worker = worker;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Factory.StartNew(worker).ContinueWith(t => { this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
}
}
Main form
public Dashboard_Form()
{
Thread t = new Thread(new ThreadStart(startform));
t.Start();
Thread.Sleep(5000);
InitializeComponent();
t.Abort();
}
Any help would be appreciated
Upvotes: 2
Views: 10775
Reputation: 6749
Use async await
if possible:
public partial class Loading_Screen : Form
{
public Loading_Screen()
{
InitializeComponent();
}
public Action Worker { get; set; }
public Loading_Screen(Action worker)
{
InitializeComponent();
Worker = worker ?? throw new ArgumentOutOfRangeException();
}
protected override async void OnLoad(EventArgs e)
{
base.OnLoad(e);
await Task.Factory.StartNew(Worker);
Close();
}
}
You usually don't need a unique thread, and since you're attempting to abort it then it's a tell sign you don't. So borrow from the thread pool in main.
public void Dashboard_Form()
{
ThreadPool.QueueUserWorkItem((o) => startform());
Thread.Sleep(5000);
InitializeComponent();
}
With this you have to implement other means to cancel the thread. I'm posting an better solution using Task
if you're open to it.
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
public async void Dashboard_Form()
{
if (cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Dispose();
cancellationTokenSource = new CancellationTokenSource();
}
var task = Task.Run(() => startform(), cancellationTokenSource.Token);
await Task.Delay(5000);
InitializeComponent();
cancellationTokenSource.Cancel();
}
This still isn't the way I would implement it personally but I believe it might get you moving in the right direction. Just look for the cancellationToken in the startForm
method and end the thread internally if it shows canceled.
Upvotes: 3