You're receiving data on background thread and trying to update the UI from the non-UI thread. You need to marshal the data from the background thread to the UI thread in order to update the control. This can be done using the Control.Invoke method.
sp.DataReceived += delegate
{
if (tb.InvokeRequired)
{
tb.Invoke(new Action(() =>
{
tb.Text += sp.ReadExisting();
}));
}
else
{
tb.Text += sp.ReadExisting();
}
}