Why when clicking button1 to start download it's never continue? - c#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tester
{
public partial class Form1 : Form
{
FileDownload fw;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Download()
{
fw = new FileDownload("http://download.microsoft.com/download/E/E/2/EE2D29A1-2D5C-463C-B7F1-40E4170F5E2C/KinectSDK-v1.0-Setup.exe", #"D:\KinetSDK.exe", 5120);
// Display progress...
Task.Factory.StartNew(() =>
{
while (!fw.Done)
{
//Console.SetCursorPosition(0, Console.CursorTop);
label1.Text = string.Format("ContentLength: {0} | BytesWritten: {1}", fw.ContentLength, fw.BytesWritten);
}
});
// Start the download...
fw.Start();
//Console.ReadKey();
}
public class FileDownload
{
private volatile bool _allowedToRun;
private string _source;
private string _destination;
private int _chunkSize;
private Lazy<int> _contentLength;
public int BytesWritten { get; private set; }
public int ContentLength { get { return _contentLength.Value; } }
public bool Done { get { return ContentLength == BytesWritten; } }
public FileDownload(string source, string destination, int chunkSize)
{
_allowedToRun = true;
_source = source;
_destination = destination;
_chunkSize = chunkSize;
_contentLength = new Lazy<int>(() => Convert.ToInt32(GetContentLength()));
BytesWritten = 0;
}
private long GetContentLength()
{
var request = (HttpWebRequest)WebRequest.Create(_source);
request.Method = "HEAD";
using (var response = request.GetResponse())
return response.ContentLength;
}
private async Task Start(int range)
{
if (!_allowedToRun)
throw new InvalidOperationException();
var request = (HttpWebRequest)WebRequest.Create(_source);
request.Method = "GET";
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.AddRange(range);
using (var response = await request.GetResponseAsync())
{
using (var responseStream = response.GetResponseStream())
{
using (var fs = new FileStream(_destination, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
while (_allowedToRun)
{
var buffer = new byte[_chunkSize];
var bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
await fs.WriteAsync(buffer, 0, bytesRead);
BytesWritten += bytesRead;
}
await fs.FlushAsync();
}
}
}
}
public Task Start()
{
_allowedToRun = true;
return Start(BytesWritten);
}
public void Pause()
{
_allowedToRun = false;
}
}
private void btnPause_Click(object sender, EventArgs e)
{
if (btnPause.Text == "Pause")
{
fw.Pause();
btnPause.Text = "Continue";
}
if (btnPause.Text == "Continue")
{
fw.Start().ContinueWith(t => label2.Text = "Done");
btnPause.Text = "Pause";
}
}
private void button1_Click(object sender, EventArgs e)
{
Download();
}
}
}
using a breakpoint it's getting to the line:
using (var fs = new FileStream(_destination, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
when i click continue i see the form1 but nothing happen. No progress on label1 and when i click on the Pause button nothing happen. And if i put a breakpoint after this line on the next line it will not get there.
It will never get to this line:
while (_allowedToRun)

Related

NetMQ Unity Pub/Sub

I'm running into some issues trying to get NetMQ to work. My code compiles fine but I'm not achieving my desired outcome. Testing both Pub and Sub side from one PC.
I have a UI Handler that is linked to four buttons, start/stop pub/sub.
Would love if someone could shed some light into the issue.
Desired outcome: To be able to transfer test.wav from "Sending Folder" to "Receiving Folder"
Publisher Logic
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
using System.IO;
public class Publisher
{
private readonly Thread _publisherThread;
private readonly Thread _subscriberThread;
public Publisher()
{
_publisherThread = new Thread(PublisherWork);
_publisherThread.Start();
_subscriberThread = new Thread(SubscriberWork);
_subscriberThread.Start();
}
public void Start()
{
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:5557");
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Sending Folder/test.wav";
byte[] fileBytes = File.ReadAllBytes(filePath);
pubSocket.SendMoreFrame("File").SendFrame(fileBytes);
}
}
private void PublisherWork()
{
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:5557"); // [C] Port
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Sending Folder/test.wav"; // [C] Filepath
byte[] fileBytes = File.ReadAllBytes(filePath);
while (true)
{
pubSocket.SendMoreFrame("File").SendFrame(fileBytes); // [C] Topic
Thread.Sleep(1000);
}
}
}
private void SubscriberWork()
{
using (var subSocket = new SubscriberSocket())
{
subSocket.Connect("tcp://localhost:5557"); // [C] Port
subSocket.Subscribe("File"); // [C] Topic
while (true)
{
var topic = subSocket.ReceiveFrameString();
var fileBytes = subSocket.ReceiveFrameBytes();
SaveWavFile(fileBytes);
}
}
}
private void SaveWavFile(byte[] fileBytes)
{
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Receiving Folder/test.wav";
File.WriteAllBytes(filePath, fileBytes);
}
}
Subscriber Logic
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
public class Subscriber : MonoBehaviour
{
public Button startButton;
public Button stopButton;
private Thread _publisherThread;
private Thread _subscriberThread;
private bool _isRunning;
private void Start()
{
startButton.onClick.AddListener(StartThreads);
stopButton.onClick.AddListener(StopThreads);
}
private void StartThreads()
{
_isRunning = true;
_publisherThread = new Thread(PublisherWork);
_publisherThread.Start();
_subscriberThread = new Thread(SubscriberWork);
_subscriberThread.Start();
}
private void StopThreads()
{
_isRunning = false;
_publisherThread.Join();
_subscriberThread.Join();
}
private void PublisherWork()
{
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:5557"); // [C] Port
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Sending Folder/test.wav"; // [C] Filepath
byte[] fileBytes = File.ReadAllBytes(filePath);
while (_isRunning)
{
pubSocket.SendMoreFrame("File").SendFrame(fileBytes); // [C] Topic
Thread.Sleep(1000);
}
}
NetMQConfig.Cleanup();
}
private void SubscriberWork()
{
using (var subSocket = new SubscriberSocket())
{
subSocket.Connect("tcp://localhost:5557"); // [C] Port
subSocket.Subscribe("File"); // [C] Topic
while (_isRunning)
{
var topic = subSocket.ReceiveFrameString();
var fileBytes = subSocket.ReceiveFrameBytes();
SaveWavFile(fileBytes);
}
}
NetMQConfig.Cleanup();
}
private void SaveWavFile(byte[] fileBytes)
{
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Receiving Folder/test.wav"; // [C]
File.WriteAllBytes(filePath, fileBytes);
}
}
UI Handler
using System.Threading;
using NetMQ;
using NetMQ.Sockets;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class UIHandler : MonoBehaviour
{
public Button startSubscriberButton;
public Button stopSubscriberButton;
public Button startPublisherButton;
public Button stopPublisherButton;
public Text pubStartStatus;
public Text pubStopStatus;
public Text subStartStatus;
public Text subStopStatus;
private Publisher _publisher;
private readonly Thread _publisherThread;
private readonly Thread _subscriberThread;
private bool _publisherRunning = false;
private bool _subscriberRunning = false;
public UIHandler()
{
// Initializing the threads
_publisherThread = new Thread(PublisherWork);
_subscriberThread = new Thread(SubscriberWork);
}
private void Start()
{
_publisher = new Publisher();
startPublisherButton.onClick.AddListener(StartPublisher);
stopPublisherButton.onClick.AddListener(StopPublisher);
startSubscriberButton.onClick.AddListener(StartSubscriber);
stopSubscriberButton.onClick.AddListener(StopSubscriber);
}
public void StartPublisher()
{
// Starting the publisher thread
_publisherThread.Start();
_publisherRunning = true;
pubStartStatus.text = "pubStartStatus: Started";
}
public void StopPublisher()
{
// Stopping the publisher thread
_publisherRunning = false;
_publisherThread.Join();
pubStopStatus.text = "pubStartStatus: Stopped";
}
public void StartSubscriber()
{
// Starting the subscriber thread
_subscriberThread.Start();
_subscriberRunning = true;
subStartStatus.text = "subStartStatus: Stopped";
}
public void StopSubscriber()
{
// Stopping the subscriber thread
_subscriberRunning = false;
_subscriberThread.Join();
subStopStatus.text = "subStartStatus: Stopped";
}
private void PublisherWork()
{
// Creating a publisher socket and binding it to the specified address
using (var pubSocket = new PublisherSocket())
{
pubSocket.Bind("tcp://*:5557");
// Reading the file bytes from the specified location
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Sending Folder/test.wav";
byte[] fileBytes = File.ReadAllBytes(filePath);
// Publishing the file bytes continuously
while (_publisherRunning)
{
pubSocket.SendMoreFrame("File").SendFrame(fileBytes);
Thread.Sleep(1000);
}
}
NetMQConfig.Cleanup();
}
private void SubscriberWork()
{
// Creating a subscriber socket and connecting it to the specified address
using (var subSocket = new SubscriberSocket())
{
subSocket.Connect("tcp://localhost:5557");
subSocket.Subscribe("File");
// Receiving and saving the file bytes continuously
while (_subscriberRunning)
{
var topic = subSocket.ReceiveFrameString();
var fileBytes = subSocket.ReceiveFrameBytes();
SaveWavFile(fileBytes);
}
}
NetMQConfig.Cleanup();
}
private void SaveWavFile(byte[] fileBytes)
{
// Saving the received file bytes to the specified location
string filePath = "C:/Users/XXXXX/Desktop/0MQ Demo/Receiving Folder/test.wav";
File.WriteAllBytes(filePath, fileBytes);
}
}

How to report to a progressBar1 using httpclient and task async when downloading multiple files?

The Downloader class :
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Download_Http
{
class Downloader
{
public delegate void DownloadProgressHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage);
public static class DownloadWithProgress
{
public static async Task ExecuteAsync(HttpClient httpClient, string downloadPath, string destinationPath, DownloadProgressHandler progress, Func<HttpRequestMessage> requestMessageBuilder = null)
{
if (requestMessageBuilder != null)
GetDefaultRequestBuilder(downloadPath);
var download = new HttpClientDownloadWithProgress(httpClient, destinationPath, requestMessageBuilder);
download.ProgressChanged += progress;
await download.StartDownload();
download.ProgressChanged -= progress;
}
private static Func<HttpRequestMessage> GetDefaultRequestBuilder(string downloadPath)
{
return () => new HttpRequestMessage(HttpMethod.Get, downloadPath);
}
}
internal class HttpClientDownloadWithProgress
{
private readonly HttpClient _httpClient;
private readonly string _destinationFilePath;
private readonly Func<HttpRequestMessage> _requestMessageBuilder;
private int _bufferSize = 8192;
public event DownloadProgressHandler ProgressChanged;
public HttpClientDownloadWithProgress(HttpClient httpClient, string destinationFilePath, Func<HttpRequestMessage> requestMessageBuilder)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
_destinationFilePath = destinationFilePath ?? throw new ArgumentNullException(nameof(destinationFilePath));
_requestMessageBuilder = requestMessageBuilder ?? throw new ArgumentNullException(nameof(requestMessageBuilder));
}
public async Task StartDownload()
{
var requestMessage = _requestMessageBuilder.Invoke();
var response = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
await DownloadAsync(response);
}
private async Task DownloadAsync(HttpResponseMessage response)
{
response.EnsureSuccessStatusCode();
var totalBytes = response.Content.Headers.ContentLength;
using (var contentStream = await response.Content.ReadAsStreamAsync())
await ProcessContentStream(totalBytes, contentStream);
}
private async Task ProcessContentStream(long? totalDownloadSize, Stream contentStream)
{
var totalBytesRead = 0L;
var readCount = 0L;
var buffer = ArrayPool<byte>.Shared.Rent(_bufferSize);
var isMoreToRead = true;
using (var fileStream = new FileStream(_destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None, _bufferSize, true))
{
do
{
var bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
isMoreToRead = false;
ReportProgress(totalDownloadSize, totalBytesRead);
continue;
}
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
readCount += 1;
if (readCount % 100 == 0)
ReportProgress(totalDownloadSize, totalBytesRead);
}
while (isMoreToRead);
}
ArrayPool<byte>.Shared.Return(buffer);
}
private void ReportProgress(long? totalDownloadSize, long totalBytesRead)
{
double? progressPercentage = null;
if (totalDownloadSize.HasValue)
progressPercentage = Math.Round((double)totalBytesRead / totalDownloadSize.Value * 100, 2);
ProgressChanged?.Invoke(totalDownloadSize, totalBytesRead, progressPercentage);
}
}
}
}
using it in form1 :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Download_Http
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private async void button1_Click(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
const string url = "https://speed.hetzner.de/100MB.bin";
Downloader.DownloadProgressHandler progressHandler = null;
await Downloader.DownloadWithProgress.ExecuteAsync(client,url, #"D:\Test\100MB.bin", progressHandler, () =>
{
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
requestMessage.Headers.Accept.TryParseAdd("application/octet-stream");
return requestMessage;
});
}
}
}
It's downloading the file but how can i report the progress to progressBar1 ? i have a ProgressBar control in form1 designer. how can i report download speed and other calculations for example to a label ?
how to create progres changed event and completed event ?
You can use a Progress object, which will marshal progress events back to the UI thread automatically.
static HttpClient _client = new HttpClient(); // always keep a single static client
private async void button1_Click(object sender, EventArgs e)
{
const string url = "https://speed.hetzner.de/100MB.bin";
IProgress<double?> progress = new Progress<double?>(percent => YourProgressBar.Value = (int)percent.GetValueOrDefault())
await Downloader.DownloadWithProgress.ExecuteAsync(
client, url, #"D:\Test\100MB.bin",
(size, bytes, percent) => progress.Report(percent),
() => {
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
requestMessage.Headers.Accept.TryParseAdd("application/octet-stream");
return requestMessage;
});
}

How to stream web cam per ASP.Net Core WebApi

I try to create an endpoint which delivers a live stream of my webcam. I´m using AForge to access the camera, but I can´t manage to create and return a stream that actually renders in a video tag in the html client.
Additionally: The MemoryStream I'm using growes every second. And that is definitly not what I want.
What I tried so far:
Cam.cs:
public class Cam
{
MemoryStream stream = new MemoryStream();
public Cam()
{
FilterInfoCollection videoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
VideoCaptureDevice finalVideo = new VideoCaptureDevice(videoCaptureDevices[0].MonikerString);
finalVideo.NewFrame += this._streamNewFrame;
finalVideo.Start();
}
private void _streamNewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
System.Drawing.Image imgforms = (Bitmap)eventArgs.Frame.Clone();
imgforms.Save(this.stream, ImageFormat.Bmp);
this.stream.Seek(0, SeekOrigin.Begin);
}
public Stream GetStream()
{
MemoryStream stream = new MemoryStream();
this.stream.CopyTo(stream);
return stream;
}
}
CamController.cs:
[ApiController]
[Route("[controller]")]
public class CamController : ControllerBase
{
private readonly Cam cam;
public CamController(Cam cam)
{
this.cam = cam;
}
[HttpGet]
public IActionResult Get()
{
var contentType = "multipart/x-mixed-replace;boundary=myboundary";
Stream stream = this.cam.GetStream();
var result = new FileStreamResult(stream, contentType)
{
EnableRangeProcessing = true,
};
return result;
}
}
Update 1:
I made progress. I managed to create a valid MJPEP stream (it is pretty easy if know how it has to look like). Look at that:
CamController.cs:
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace demo.Controllers
{
[ApiController]
[Route("[controller]")]
public class CamController : ControllerBase
{
private readonly Cam cam;
public CamController(Cam cam)
{
this.cam = cam;
}
[HttpGet]
[Route("cam/video")]
public async Task Get()
{
Response.ContentType = "video/webm";
// How to go on here?
}
[HttpGet]
[Route("cam/mjepg")]
public async Task Get2()
{
Response.StatusCode = 206;
Response.ContentType = "multipart/x-mixed-replace; boundary=frame";
Response.Headers.Add("Connection", "Keep-Alive");
StreamingSession session = this.cam.StreamOn(data =>
{
if (Request.HttpContext.RequestAborted.IsCancellationRequested)
{
throw new Exception();
}
Response.Body.Write(this.CreateHeader(data.Length));
Response.Body.Write(data);
Response.Body.Write(this.CreateFooter());
Response.Body.Flush();
});
await Response.StartAsync();
await session.WaitAsync();
}
/// <summary>
/// Create an appropriate header.
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
private byte[] CreateHeader(int length)
{
string header =
"--frame" + "\r\n" +
"Content-Type:image/jpeg\r\n" +
"Content-Length:" + length + "\r\n\r\n";
return Encoding.ASCII.GetBytes(header);
}
private byte[] CreateFooter()
{
return Encoding.ASCII.GetBytes("\r\n");
}
}
}
Cam.cs:
using AForge.Video.DirectShow;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace demo
{
public class Cam
{
object locker = new object();
bool signaledToStop = false;
List<StreamingSession> sessions = new List<StreamingSession>();
VideoCaptureDevice finalVideo;
public Cam()
{
FilterInfoCollection videoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
finalVideo = new VideoCaptureDevice(videoCaptureDevices[0].MonikerString);
finalVideo.VideoResolution = finalVideo.VideoCapabilities
.OrderByDescending(x => x.MaximumFrameRate)
.ThenByDescending(x=>x.FrameSize.Width)
.FirstOrDefault();
finalVideo.NewFrame += this._streamNewFrame;
}
private void _streamNewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
System.Drawing.Image imgforms = (Bitmap)eventArgs.Frame.Clone();
byte[] data = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
imgforms.Save(stream, ImageFormat.Jpeg);
data = stream.ToArray();
}
lock (this.locker)
{
foreach (var session in sessions.ToList())
{
session.ProvideData(data);
}
}
}
public StreamingSession StreamOn(Action<byte[]> callback)
{
StreamingSession session = new StreamingSession(callback);
lock (this.locker)
{
this.sessions.Add(session);
if (this.signaledToStop)
{
this.finalVideo.WaitForStop();
}
if (!this.finalVideo.IsRunning)
{
this.finalVideo.Start();
this.signaledToStop = false;
}
}
session.OnSessionEnded += Session_OnSessionEnded;
return session;
}
private void Session_OnSessionEnded(object sender, EventArgs e)
{
lock(this.locker)
{
this.sessions.Remove(sender as StreamingSession);
if (!this.sessions.Any())
{
this.finalVideo.SignalToStop();
this.signaledToStop = true;
}
}
}
}
public class StreamingSession
{
public StreamingSession(Action<byte[]> Callback)
{
this.Callback = Callback;
}
private Action<byte[]> Callback;
private TaskCompletionSource Completion = new TaskCompletionSource();
public event EventHandler OnSessionEnded;
public Task WaitAsync(int? timeout = null)
{
if (timeout.HasValue)
{
return Task.WhenAny(Task.Delay(timeout.Value), this.Completion.Task);
}
return this.Completion.Task;
}
public void ProvideData(byte[] data)
{
try
{
this.Callback(data);
}
catch(Exception)
{
this.EndSession();
}
}
public void EndSession()
{
this.Completion.SetResult();
if (this.OnSessionEnded != null)
{
this.OnSessionEnded(this, null);
}
}
}
}
But there is a problem left: The "video" (more like moving images) only renders in an img tag. But it shall render in a video tag. I read that video tag doesn´t support mjpeg - but how can I encode the stream in a format the video tag understands?
I uploaded the complete code here: https://github.com/ChristophWieske/asp-net-core-live-stream-source
You may want to consider WebRTC.
WebRTC is a relatively new browser based technology that allows a server to send streams to a JavaScript client.
See the WebRTC Samples for client side code: https://github.com/webrtc/samples
Server side code is a bit more complex. Here's an overly complicated example that uses "Mixed Reality." It's a bit overboard, but should point you in the right direction.
https://microsoft.github.io/MixedReality-WebRTC/manual/cs/helloworld-cs-connection-core3.html

How to edit my code to run in console rather than GUI

I was following a tutorial to connect my bluetooth module to pc and read data from it, but in the tutorial he designed the program to run as a GUI, now I'm trying to edit it to run in console, which I will merge the new code in unity engine to move my game by the input data.
The GUI
used and the code,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using InTheHand;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using System.IO;
namespace Bluetooth
{
public partial class Form1 : Form
{
List<string> items;
public Form1()
{
items = new List<string>();
InitializeComponent();
}
private void bGo_Click(object sender, EventArgs e)
{
if(serverStarted)
{
updateUI("Server already started!");
return;
}
if(rbClient.Checked)
{
connectAsClient();
}
else
{
connectAsServer();
}
}
private void connectAsServer()
{
Thread bluetoothServerThread = new Thread(new ThreadStart(serverConnectThread));
bluetoothServerThread.Start();
}
Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");
bool serverStarted = false;
public void serverConnectThread()
{
serverStarted = true;
updateUI("Server started, waiting for clients");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
BluetoothClient conn = blueListener.AcceptBluetoothClient();
updateUI("Client has connected");
Stream mstream = conn.GetStream();
while (true)
{
try
{
//handle server connection
byte[] received = new byte[1024];
mstream.Read(received, 0, received.Length);
updateUI("Received: " + Encoding.ASCII.GetString(received));
byte[] sent = Encoding.ASCII.GetBytes("Hello world\n");
mstream.Write(sent, 0, sent.Length);
}
catch (IOException exception)
{
updateUI("Client has disconnected!!");
break;
}
}
}
private void connectAsClient()
{
startScan();
}
private void startScan()
{
listBox1.DataSource = null;
listBox1.Items.Clear();
items.Clear();
Thread bluetoothScanThread = new Thread(new ThreadStart(scan));
bluetoothScanThread.Start();
}
BluetoothDeviceInfo[] devices;
private void scan()
{
updateUI("Start scanning...");
BluetoothClient client = new BluetoothClient();
devices = client.DiscoverDevicesInRange();
updateUI(devices.Length.ToString() + " devices discovered");
updateUI("Scan complete");
foreach(BluetoothDeviceInfo d in devices)
{
items.Add(d.DeviceName);
}
updateDeviceList();
}
private void updateUI(string message)
{
Func<int> del = delegate ()
{
tbOutput.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateDeviceList()
{
Func<int> del = delegate ()
{
listBox1.DataSource = items;
return 0;
};
Invoke(del);
}
BluetoothDeviceInfo DeviceInfo;
private void listBox1_DoubleClick(object sender, EventArgs e)
{
DeviceInfo = devices.ElementAt(listBox1.SelectedIndex);
updateUI(DeviceInfo.DeviceName + " was Selected, attempting connect");
if(PairDevice())
{
updateUI("Device paired");
updateUI("starting connect thread");
Thread bluetoothClientThread = new Thread(new ThreadStart(ClientConnectThread));
bluetoothClientThread.Start();
}
else
{
updateUI("pair failed");
}
}
private void ClientConnectThread()
{
BluetoothClient client = new BluetoothClient();
updateUI("Attempting connect");
client.BeginConnect(DeviceInfo.DeviceAddress, mUUID, this.BluetoothClientConnectCallback, client);
}
void BluetoothClientConnectCallback(IAsyncResult result)
{
BluetoothClient client = (BluetoothClient)result.AsyncState;
client.EndConnect(result);
Stream stream = client.GetStream();
stream.ReadTimeout = 10000;
while(true)
{
try
{
byte[] received = new byte[1024];
stream.Read(received, 0, received.Length);
updateUI(Encoding.ASCII.GetString(received));
}
catch (IOException exception)
{
updateUI("Client has disconnected!!");
break;
}
}
}
string mypin = "1234";
private bool PairDevice()
{
if(!DeviceInfo.Authenticated)
{
if (!BluetoothSecurity.PairRequest(DeviceInfo.DeviceAddress, mypin)) ;
{
return false;
}
}
return true;
}
bool ready = false;
byte[] message;
private void tbText_KeyPress(object sender, KeyPressEventArgs e)
{
if(e.KeyChar == 13)
{
byte[] b = Encoding.ASCII.GetBytes(tbText.Text);
ready = true;
tbText.Clear();
}
}
}
}
I tried to edit my code but I don't know why scan method can't be called.
class Program
{
Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");
List<string> items = new List<string>();
BluetoothDeviceInfo[] devices;
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Thread bluetoothScanThread = new Thread(new ThreadStart(scan));
bluetoothScanThread.Start();
}
public void scan()
{
Console.WriteLine("Start scanning...");
BluetoothClient client = new BluetoothClient();
devices = client.DiscoverDevicesInRange();
Console.WriteLine(devices.Length.ToString() + " devices discovered");
Console.WriteLine("Scan complete");
foreach (BluetoothDeviceInfo d in devices)
{
items.Add(d.DeviceName);
}
}
}

Handling multiple nested asyncs

I am having an issue working with async methods - namely nested async.
I start off a background task:
public sealed class StartupTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
ServerWorkers.WebServer server = new ServerWorkers.WebServer();
await ThreadPool.RunAsync(workItem =>
{
AnotherSync.Get();
server.Start();
});
}
public static async void Get()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Shared.URL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Shared.HeaderType));
using (var response = await client.GetAsync(route + "?" + GeneralTags.COMPANY_REF + "=" + ApplicationObject.CompanyRef)) //.Result)
{
if (response.IsSuccessStatusCode)
{
ApplicationObject.PrintData = JsonConvert.DeserializeObject<Model.Print>(response.Content.ReadAsStringAsync().Result);
}
else
{
evError(new Exception(String.Format("{0}: {1}", (int)response.StatusCode, response.ReasonPhrase)), ErrorTags.PRINT_GET);
}
}
}
}
internal class WebServer
{
private const uint BufferSize = 8192;
public void Start()
{
StreamSocketListener listener = new StreamSocketListener();
listener.BindServiceNameAsync("8080");
listener.ConnectionReceived += async (sender, args) =>
{
StringBuilder request = new StringBuilder();
using (IInputStream input = args.Socket.InputStream)
{
byte[] data = new byte[BufferSize];
IBuffer buffer = data.AsBuffer();
uint 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 (IOutputStream output = args.Socket.OutputStream)
{
using (Stream response = output.AsStreamForWrite())
{
byte[] bodyArray = Encoding.UTF8.GetBytes("<html><body>Hello, World!</body></html>");
var bodyStream = new MemoryStream(bodyArray);
var header = "HTTP/1.1 200 OK\r\n" +
$"Content-Length: {bodyStream.Length}\r\n" +
"Connection: close\r\n\r\n";
byte[] headerArray = Encoding.UTF8.GetBytes(header);
await response.WriteAsync(headerArray, 0, headerArray.Length);
await bodyStream.CopyToAsync(response);
await response.FlushAsync();
}
}
};
}
}
Then my app acts a web server.. It does not exit out.
If I add this so I have:
public async void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
ServerWorkers.WebServer server = new ServerWorkers.WebServer();
await ThreadPool.RunAsync(workItem =>
{
AnotherSync.Get();
AnotherSync.Get();
server.Start();
});
}
internal class AnotherSync
{
public static event delError evError;
private const string route = "/api/Print";
static wsPrint.IPrint wsPrint = new wsPrint.PrintClient();
public static void Get()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Shared.URL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Shared.HeaderType));
using (var response = client.GetAsync(route + "?" + GeneralTags.COMPANY_REF + "=" + ApplicationObject.CompanyRef).Result)
{
if (response.IsSuccessStatusCode)
{
ApplicationObject.PrintData = JsonConvert.DeserializeObject<Model.Print>(response.Content.ReadAsStringAsync().Result);
}
else
{
evError(new Exception(String.Format("{0}: {1}", (int)response.StatusCode, response.ReasonPhrase)), ErrorTags.PRINT_GET);
}
}
}
}
}
then the application exists out.
I may be mistaken but is it because I am using nested async methods?
This is an example of what a thread should look like,
public sealed class StartupTask : IBackgroundTask
{
//has to be declared here to keep the handle alive and prevent garbage collection
private ServerWorkers.WebServer server = new ServerWorkers.WebServer();
public async void Run(IBackgroundTaskInstance taskInstance)
{
//Start the server running no need for await as its an synchronous
server.Start();
//don't exit until work is compelted
while(server.Running)
{
//give up processor and allow other work to occur while you are waiting
await Task.Yield();
}
}
internal class WebServer
{
private const uint BufferSize = 8192;
private StreamSocketListener listener;
public bool Running { get; private set;}= false;
public void Start()
{
Lock(this){//prevent any other code interupting
if(!Running )//prevent multiple starts
{
listener = new StreamSocketListener();
listener.BindServiceNameAsync("8080");
listener.ConnectionReceived += listener_ConnectionReceived;
Running = true;
}
}
}
public void Stop()
{
Lock(this){//prevent any other code interupting
listener.Close();
listener.Dispose();
listener = null;
Running = false;
}
}
public void listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
//process data from listerner's event
}
}
}
Note i'm not using the Windows Application Framework so might be different there

Categories

Resources