Я относительно новичок в написании приложений для Windows IoT.У меня есть фоновое приложение Windows IoT, в котором я хочу создать три отдельных потока из основного потока.(Причина, по которой я хочу, чтобы все они выполнялись в отдельных фоновых потоках, заключается в том, что часть выполняемой ими работы может занимать много времени, поэтому я, очевидно, не хочу ничего блокировать).
ПервыйВ потоке запущен небольшой веб-сервер.
Второй поток прослушивает выводы GPIO на Raspberry PI.
Третий поток для прослушивания устройств через I2C.
По некоторым причинам я не могу заставить все три потока оставаться открытыми.Вот мой код из StartupTask:
public sealed class StartupTask : IBackgroundTask
{
private static BackgroundTaskDeferral _Deferral = null;
public async void Run(IBackgroundTaskInstance taskInstance)
{
_Deferral = taskInstance.GetDeferral();
// do some stuff on the main thread here...
// thread 1
var webserver = new TestWebserver();
await ThreadPool.RunAsync(workItem =>
{
webserver.Start();
});
// thread 2
var masterEventListener = new MasterEventListener();
await ThreadPool.RunAsync(workItem =>
{
masterEventListener.Start();
});
// thread 3
var i2cEventListener = new I2CEventListener();
await ThreadPool.RunAsync(workItem =>
{
i2cEventListener.Start();
});
}
}
Вот оболочка для первого потока:
internal class TestWebserver
{
private const uint BufferSize = 8192;
public async void Start()
{
var listener = new StreamSocketListener();
await listener.BindServiceNameAsync(8081);
listener.ConnectionReceived += async (sender, args) =>
{
var request = new StringBuilder();
using (var input = args.Socket.InputStream)
{
var data = new byte[BufferSize];
IBuffer buffer = data.AsBuffer();
var dataRead = BufferSize;
while (dataRead == BufferSize)
{
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
dataRead = buffer.Length;
}
}
using (var output = args.Socket.OutputStream)
{
using (var response = output.AsStreamForWrite())
{
string html = "TESTING RESPONSE";
using (var bodyStream = new MemoryStream(html))
{
var header = $"HTTP/1.1 200 OK\r\nContent-Length: {bodyStream.Length}\r\n\r\nConnection: close\r\n\r\n";
var headerArray = Encoding.UTF8.GetBytes(header);
await response.WriteAsync(headerArray, 0, headerArray.Length);
await bodyStream.CopyToAsync(response);
await response.FlushAsync();
}
}
}
};
}
}
Вот оболочка для второго потока:
internal class MasterEventListener
{
public void Start()
{
GpioController gpio = GpioController.GetDefault();
GpioPin gpioPin = gpio.OpenPin(4); // pin4
if (gpioPin.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
{
gpioPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
}
else
{
gpioPin.SetDriveMode(GpioPinDriveMode.Input);
}
gpioPin.Write(GpioPinValue.High);
gpioPin.DebounceTimeout = TimeSpan.FromMilliseconds(25);
gpioPin.ValueChanged += Pin_ValueChanged;
}
private void Pin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
bool value = sender.Read() == GpioPinValue.High;
if (value)
{
Debug.WriteLine("OPEN!");
}
else
{
Debug.WriteLine("CLOSED!");
}
}
}
А вот оболочка для третьего потока:
internal class I2CEventsListener
{
public async void Start()
{
string aqs = I2cDevice.GetDeviceSelector();
DeviceInformationCollection dis = await DeviceInformation.FindAllAsync(aqs);
I2CThreadListener(dis);
}
private async void I2CThreadListener(DeviceInformationCollection dis)
{
while(true)
{
var settings = new I2cConnectionSettings(3); // I2C address 3
settings.BusSpeed = I2cBusSpeed.FastMode;
settings.SharingMode = I2cSharingMode.Shared;
using (I2cDevice device = await I2cDevice.FromIdAsync(dis[0].Id, settings))
{
if (device != null)
{
try
{
byte[] writeBuffer = Encoding.ASCII.GetBytes("000000");
byte[] readBuffer = new byte[7];
device.Write(writeBuffer);
device.Read(readBuffer);
var str = Encoding.Default.GetString(readBuffer);
if (str != null && str.Trim().Length == 7 && Convert.ToInt32(readBuffer[0]) > 0)
{
Debug.WriteLine("RESULTS! '" + str + "'");
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
}
Thread.Sleep(100);
}
});
}
Если я закомментирую какой-либо из двух потоков, оставшийся поток будет работать бесконечно и будет работать отлично.
Если я закомментирую один поток, оставшиеся два потока будут работать идеально (иногда) около 30 секунд, а затем один из потоков прекратит работу с таким сообщением:
The thread 0xad0 has exited with code 0 (0x0).
Я никогда не получаю никаких сообщений об ошибках в своих журналах, поэтому я не верю, что выдается какая-либо ошибка.
И я вижу ожидаемые результаты - до тех пор, пока я запускаю только один из потоков.Но как только у меня работает несколько потоков, это вызывает проблемы.
Любое направление будет с благодарностью.
Спасибо, ребята ...