Please see my comment to the question. You need to use some set of facilities. 1) to express parallelism in behavior of actors, such as the user/player and characters like snakes, 2) calculate change in states expressing the scenario of game, 3) calculate "physics", such as collisions, 4) calculate graphical scene, 5) render it.
In most or all of the aspects, you are choosing wrong or inappropriate facility, or miss some. Below, I'll try to cover just some.
Using
PictureBox
does not give you any help, only adds problems, uses some resources you don't need to use and wastes your development time. It happens each time you try to use this purely redundant control to anything except rendering static images. The problem is easily solved by rendering graphics from scratch. I explained it all in my past answers:
Append a picture within picturebox[
^],
How do I clear a panel from old drawing[
^],
draw a rectangle in C#[
^],
rendering:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[
^],
capture the drawing on a panel[
^],
Drawing Lines between mdi child forms[
^],
with threads:
How to speed up my vb.net application?[
^].
See also:
How to avoid Red Cross in DatagridView C#[
^],
any way to change a picture at run time with animation[
^],
how to make a file from the content of e.graphics[
^].
Some of the links above already explain how to work with threads, but here you need to take a step back and get to using them in general. First of all, avoid timers. Haven't you already face such situation where you have a timer event triggered when the previous event is not yet handled? With timers, sooner or later, you will. And so on… With threads, there are no such problems. It's important that you should not rely on any fixed period of time. You should take real time value from
System.DateTime.Now
or, with better accuracy, relative timing with
System.Diagnostics.Stopwatch
:
https://msdn.microsoft.com/en-us/library/system.datetime%28v=vs.110%29.aspx[
^],
https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch%28v=vs.110%29.aspx[
^].
You cannot call anything related to UI from non-UI thread. Instead, you need to use the method
Invoke
or
BeginInvoke
of
System.Windows.Threading.Dispatcher
(for both Forms or WPF) or
System.Windows.Forms.Control
(Forms only).
You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.
See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.
Also, please see this answer where I explain how can you smoothly exchange data between threads and encapsulate it in a thread-safe way:
How to pass ref parameter to the thread[
^],
Change parameters of thread (producer) after it is started[
^],
MultiThreading in C#[
^],
Passing arguments to a threaded LongRunningProcess[
^],
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)[
^],
Making Code Thread Safe[
^].
Long live snakes!
—SA