i need a small help with my app. When I press the button the app freezes until ssh complete the commnand which was sent. I tried solution from C# application freezes but when I tried to use Task.Factory.StartNew(()... i dont have a output in console. There is my code:
var cmd = SSH.CreateCommand("apt update && apt upgrade -y");
var asynch = cmd.BeginExecute();
var reader = new StreamReader(cmd.OutputStream);
while (!asynch.IsCompleted)
{
var result = reader.ReadToEnd();
if (string.IsNullOrEmpty(result))
continue;
Console.Write(result);
}
cmd.EndExecute(asynch);
Does anyone have anything to do with it?
You are probably blocking your GUI thread with your while loop.
You need to run your code async.
public static void Main(String[] args)
{
Task sshTask = RunCommand();
}
public static async Task RunCommand()
{
var cmd = SSH.CreateCommand("apt update && apt upgrade -y");
var asynch = cmd.BeginExecute();
var reader = new StreamReader(cmd.OutputStream);
while (!asynch.IsCompleted)
{
var result = reader.ReadToEnd();
if (string.IsNullOrEmpty(result))
continue;
Console.Write(result);
}
cmd.EndExecute(asynch);
}
Related
So I am trying to build a program to control a machine. Communications with said machine is via a serial port for which I have written a driver. Continuous polling to the machine is necessary for status feedback etc. In my program I have a dedicated ExecutionEngine() class to handle serial send and receive. I also need to have two separate control sequences running, which I have put into methods RunSequenceA() and RunSequenceB() respectively. During normal operation, all three methods need to run until both control sequences finish, at which point the StopSequence() method is called. My issue is that sometimes, for whatever reason, the StopSequence() method is never called, leaving my ExecutionEngine() method in an infinite loop!
Code for ExecutionEngine():
private static void ExecutionEngine()
{
// Clear both lists in case they have old data
_commandList.Clear();
_pollingList.Clear();
// Poll while user has not yet clicked "STOP"
while (!_cTokenSource.Token.IsCancellationRequested)
{
// If there are commands to be sent, send them first
if (_commandList.Count > 0)
{
Command[] tempCommandArray;
lock (_commandList)
tempCommandArray = _commandList.ToArray();
foreach (var c in tempCommandArray)
{
if (_cTokenSource.Token.IsCancellationRequested)
break;
var response = SerialDriver.ComCycle(c.CommandBytes, _serialPort);
var success = CheckErrorReturn(response, false);
if (success)
{
AddPolling(c);
RemoveCommand(c);
}
}
}
// Do polling operation on applicable controllers
if (_pollingList.Count > 0)
{
Command[] tempPollingArray;
lock (_pollingList)
tempPollingArray = _pollingList.ToArray();
foreach (var c in tempPollingArray)
{
if (_cTokenSource.Token.IsCancellationRequested)
break;
var response = SerialDriver.ComCycle(c.PollBytes, _serialPort);
var success = ProcessPollReturn(response);
if (success)
{
c.FlagDone();
RemovePolling(c);
}
}
}
if (_commandList.Count + _pollingList.Count == 0)
{
// Will get stuck here if neither list gets new items added
Console.WriteLine("Bad place");
Thread.Sleep(500);
}
}
// Cancellation has been requested
lock (_commandList)
_commandList.Clear();
lock (_pollingList)
_pollingList.Clear();
ResetTriggers();
var endCommand = new Command("GL_SYSCMD", 0);
SerialDriver.ComCycle(endCommand.CommandBytes, _serialPort);
_serialPort.Close();
_vm.SequenceRunning = false;
return;
}
Code for running sequences:
private static async Task RunSequencesAsync()
{
var taskArray = new Task[2];
var a = new Action(RunSequenceA);
var b = new Action(RunSequenceB);
taskArray[0] = Task.Run(a);
taskArray[1] = Task.Run(b);
await Task.WhenAll(taskArray).ConfigureAwait(continueOnCapturedContext: false);
// Sometimes this never fires, WHY?
UpdateStatus("All done!");
StopSequence();
}
// Run A sequence
internal static void RunSequenceA()
{
if (_sequenceA1 != null && _sequenceA1.Count > 0)
{
foreach (var s in _sequenceA1)
{
if (_cTokenSource.Token.IsCancellationRequested)
return;
s.Execute();
if (s.Reference != null && TriggerStepCompleted != null)
TriggerStepCompleted(s, EventArgs.Empty);
}
// This part always fires
Console.WriteLine("Sequence A finished");
return;
}
else
return;
}
And finally, the methods to start and stop everything:
private static async Task StartSequenceAsync()
{
_serialPort.PortName = _vm.SelectedComPort;
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
// Start
_cTokenSource = new CancellationTokenSource();
_vm.SequenceRunning = true;
var taskArray = new Task[2];
taskArray[0] = Task.Run(() => ExecutionEngine());
Thread.Sleep(50);
taskArray[1] = Task.Run(() => RunSequencesAsync());
await Task.WhenAll(taskArray).ConfigureAwait(continueOnCapturedContext: false);
}
private static void StopSequence()
{
_cTokenSource.Cancel();
}
To reiterate, the problem doesn't happen every time. In fact, most times the program runs fine. It seems that problems only arise if I manually call the StopSequence() method half way through execution. Then it's 50/50 as to whether the problem shows up. I'm pretty sure my issue is threading related, but not sure exactly what is going wrong. Any help pointing me in the right direction will be greatly appreciated!
I'm trying to run a Thread infinitely, but it's not working ...
Follow the code:
namespace BTCPrice
{
public static class Price
{
private static volatile bool _shouldStop = false;
public static void RequestStop()
{
_shouldStop = true;
}
public static void Refresh(out string value, int tipo = 0, string source = "https://www.mercadobitcoin.net/api/")
{
while (_shouldStop == false)
{
JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
WebClient cliente = new WebClient();
string json = cliente.DownloadString(string.Format("{0}/{1}/{2}", source, "BTC", "ticker"));
JObject j = JObject.Parse(json);
switch (tipo)
{
//Get High Price
case 0:
value = j["ticker"]["high"].ToString();
break;
//Get Low Price
case 1:
value = j["ticker"]["low"].ToString();
break;
default:
value = "default";
break;
}
Thread.Sleep(1000);
}
value = "Stopped";
}
}
}
On Start:
string result = "";
Thread workerThread = new Thread(() => {
Price.Refresh(out result);
MessageBox.Show(result);
Invoke(textBox1, result);
Thread.Sleep(1000);
});
No exception occurs ... as long as I remove the While (_shouldStop == false) class the code works perfectly. However, I would like that, while the program is open, it executes the code and updates the textbox with the value that I get by the API.
result without While(_shouldStop == false) in class:
Expected Result with While
You really shouldn't be using threads these days when there are excellent alternatives that handle all of the mess for you.
I'd suggest using Microsoft's Reactive Framework (aka "Rx"). Just NuGet "System.Reactive", "System.Reactive.Windows.Forms" (Windows Forms), "System.Reactive.Windows.Threading" (WPF).
Then you can do this:
int tipo = 0;
string source = "https://www.mercadobitcoin.net/api/";
string url = string.Format("{0}/{1}/{2}", source, "BTC", "ticker");
IObservable<string> feed =
from n in Observable.Interval(TimeSpan.FromSeconds(1.0))
from json in Observable.Using<string, WebClient>(() => new WebClient(), cliente => cliente.DownloadStringTaskAsync(url).ToObservable())
let j = JObject.Parse(json)
let high = j["ticker"]["high"].ToString()
let low = j["ticker"]["low"].ToString()
select tipo == 0 ? high : (tipo == 1 ? low : "default");
IDisposable subscription =
feed
.ObserveOn(this); // for Windows Forms OR .ObservableOnDispatcher() for WPF
.Subscribe(value =>
{
/* Do something with `value` */
});
You'll now get a steady stream of the string value every second. A thread is started automatically and the results are automatically pasted to the UI thread.
When you want to stop the feed producing values just call subscription.Dispose();.
This code entirely replaces your Price class.
Change your while loop in Price.Refresh to inside the thread. Have Price.Refresh return a string instead.
Thread workerThread = new Thread(() => {
while (true)
{
String result = Price.Refresh();
MessageBox.Show(result);
Invoke(textBox1, result);
Thread.Sleep(1000);
});
I agree with Scott Chamberlain in that you should use a timer instead and rewrite this but this will work for you.
I tried using returnString.CallAsync(); to a smart contract function that returns bytes or string but Im getting null. Would you know why this is the case with functions that return string or bytes and not int? I am using nethereum as the .net client for ethereum.
here is my contract
contract A {
string myString = "someString";
function A(int multiplier) {
}
function getMyString() returns (bytes) {
bytes memory b3 = bytes(myString);
return b3;
}
}
Here is my .net nethereum code:
var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c";
var password = "password";
var abi = #"[{""constant"":false,""inputs"":[],""name"":""getMyString"",""outputs"":[{""name"":"""",""type"":""bytes""}],""payable"":false,""type"":""function""},{""inputs"":[{""name"":""multiplier"",""type"":""int256""}],""payable"":false,""type"":""constructor""}]";
var byteCode =
"0x60a0604052600a60608190527f736f6d65537472696e6700000000000000000000000000000000000000000000608090815261003e9160009190610060565b50341561004757fe5b6040516020806102a383398101604052515b5b50610100565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a157805160ff19168380011785556100ce565b828001600101855582156100ce579182015b828111156100ce5782518255916020019190600101906100b3565b5b506100db9291506100df565b5090565b6100fd91905b808211156100db57600081556001016100e5565b5090565b90565b6101948061010f6000396000f300606060405263ffffffff60e060020a6000350416637e7b8a968114610021575bfe5b341561002957fe5b6100316100b1565b604080516020808252835181830152835191928392908301918501908083838215610077575b80518252602083111561007757601f199092019160209182019101610057565b505050905090810190601f1680156100a35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100b9610156565b6100c1610156565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101475780601f1061011c57610100808354040283529160200191610147565b820191906000526020600020905b81548152906001019060200180831161012a57829003601f168201915b505050505090508091505b5090565b604080516020810190915260008152905600a165627a7a72305820eb300cf43a9ba95dde6cd63161d8229e787f1e4daf4f549c303011176546f2ba0029";
var web3 = new Web3.Web3();
var unlockAccountResult =
await web3.Personal.UnlockAccount.SendRequestAsync(senderAddress, password, 120);
var transactionHash =
await web3.Eth.DeployContract.SendRequestAsync(abi, byteCode, senderAddress, 1);
var mineResult = await web3.Miner.Start.SendRequestAsync(6);
var receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(transactionHash);
while (receipt == null)
{
Thread.Sleep(5000);
receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(transactionHash);
}
mineResult = await web3.Miner.Stop.SendRequestAsync();
var contractAddress = receipt.ContractAddress;
var contract = web3.Eth.GetContract(abi, contractAddress);
var returnString = contract.GetFunction("getMyString");
byte[] result2 = await returnString.CallAsync<byte[]>();
while (result2 == null)
{
Thread.Sleep(5000);
result2 = await returnString.CallAsync<byte[]>();
}
When running on local Ganache, this contract works fine (the correct string is returned). No need to mine or to wait.
I've created a example project here https://github.com/StefH/Solidity-Examples/tree/master/SmartContracts/Examples/GetString.
Go to Solidity folder and run npm i and npm run build to generate C# interface and implementation files.
In the ConsoleApp folder there is a example dotnet core console app which outputs like:
Blockchain - Ganache - ConsoleApp
________________________________________________________________________________
DeployContractAsync
Call GetMyStringCallAsync
result = `someString`
________________________________________________________________________________
I would like to seek your help in implementing Multi-Threading in my C# program.
The program aims to upload 10,000++ files to an ftp server. I am planning to implement atleast a minimum of 10 threads to increase the speed of the process.
With this, this is the line of code that I have:
I have initialized 10 Threads:
public ThreadStart[] threadstart = new ThreadStart[10];
public Thread[] thread = new Thread[10];
My plan is to assign one file to a thread, as follows:
file 1 > thread 1
file 2 > thread 2
file 3 > thread 3
.
.
.
file 10 > thread 10
file 11 > thread 1
.
.
.
And so I have the following:
foreach (string file in files)
{
loop++;
threadstart[loop] = new ThreadStart(() => ftp.uploadToFTP(uploadPath + #"/" + Path.GetFileName(file), file));
thread[loop] = new Thread(threadstart[loop]);
thread[loop].Start();
if (loop == 9)
{
loop = 0;
}
}
The passing of files to their respective threads is working. My problem is that the starting of the thread is overlapping.
One example of exception is that when Thread 1 is running, then a file is passed to it. It returns an error since Thread 1 is not yet successfully done, then a new parameter is being passed to it. Also true with other threads.
What is the best way to implement this?
Any feedback will be greatly appreciated. Thank you! :)
Using async-await and just pass an array of files into it:
private static async void TestFtpAsync(string userName, string password, string ftpBaseUri,
IEnumerable<string> fileNames)
{
var tasks = new List<Task<byte[]>>();
foreach (var fileInfo in fileNames.Select(fileName => new FileInfo(fileName)))
{
using (var webClient = new WebClient())
{
webClient.Credentials = new NetworkCredential(userName, password);
tasks.Add(webClient.UploadFileTaskAsync(ftpBaseUri + fileInfo.Name, fileInfo.FullName));
}
}
Console.WriteLine("Uploading...");
foreach (var task in tasks)
{
try
{
await task;
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
Then call it like this:
const string userName = "username";
const string password = "password";
const string ftpBaseUri = "ftp://192.168.1.1/";
var fileNames = new[] { #"d:\file0.txt", #"d:\file1.txt", #"d:\file2.txt" };
TestFtpAsync(userName, password, ftpBaseUri, fileNames);
Why doing it the hard way?
.net already has a class called ThreadPool.
You can just use that and it manages the threads itself.
Your code will be like this:
static void DoSomething(object n)
{
Console.WriteLine(n);
Thread.Sleep(10);
}
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(20, 10);
for (int x = 0; x < 30; x++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomething), x);
}
Console.Read();
}
I'm asynchronously retrieving some rss articles with my Portable Class Library that uses the Microsoft.Bcl library (which doesn't have Task.WhenAll). Each article has a url to rss comments that I need to asynchronously retrieve as well.
The code below is my library. I call GetArticles() but it does not return any of the which creates a list of tasks that call GetComments() to asynchronously get the comments.
I've tried using Task.WaitAll in GetArticles to wait for the comments but it does not block the thread. Any help would be appreciated.
private const string ArticlesUri = "";
public async Task<List<ArticleBrief>> GetArticles()
{
var results = new List<ArticleBrief>();
try
{
var wfw = XNamespace.Get("http://wellformedweb.org/CommentAPI/");
var media = XNamespace.Get("http://search.yahoo.com/mrss/");
var dc = XNamespace.Get("http://purl.org/dc/elements/1.1/");
var t = await WebHttpRequestAsync(ArticlesUri);
StringReader stringReader = new StringReader(t);
using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
{
var doc = System.Xml.Linq.XDocument.Load(xmlReader);
results = (from e in doc.Element("rss").Element("channel").Elements("item")
select
new ArticleBrief()
{
Title = e.Element("title").Value,
Description = e.Element("description").Value,
Published = Convert.ToDateTime(e.Element("pubDate").Value),
Url = e.Element("link").Value,
CommentUri = e.Element(wfw + "commentRss").Value,
ThumbnailUri = e.Element(media + "thumbnail").FirstAttribute.Value,
Categories = GetCategoryElements(e.Elements("category")),
Creator = e.Element(dc + "creator").Value
}).ToList();
}
var tasks = new Queue<Task>();
foreach (var result in results)
{
tasks.Enqueue(
Task.Factory.StartNew(async ()=>
{
result.Comments = await GetComments(result.CommentUri);
}
));
}
Task.WaitAll(tasks.ToArray());
}
catch (Exception ex)
{
// should do some other
// logging here. for now pass off
// exception to callback on UI
throw ex;
}
return results;
}
public async Task<List<Comment>> GetComments(string uri)
{
var results = new List<Comment>();
try
{
var wfw = XNamespace.Get("http://wellformedweb.org/CommentAPI/");
var media = XNamespace.Get("http://search.yahoo.com/mrss/");
var dc = XNamespace.Get("http://purl.org/dc/elements/1.1/");
var t = await WebHttpRequestAsync(uri);
StringReader stringReader = new StringReader(t);
using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
{
var doc = System.Xml.Linq.XDocument.Load(xmlReader);
results = (from e in doc.Element("rss").Element("channel").Elements("item")
select
new Comment()
{
Description = e.Element("description").Value,
Published = Convert.ToDateTime(e.Element("pubDate").Value),
Url = e.Element("link").Value,
Creator = e.Element(dc + "creator").Value
}).ToList();
}
}
catch (Exception ex)
{
// should do some other
// logging here. for now pass off
// exception to callback on UI
throw ex;
}
return results;
}
private static async Task<string> WebHttpRequestAsync(string url)
{
//TODO: look into getting
var request = WebRequest.Create(url);
request.Method = "GET";
var response = await request.GetResponseAsync();
return ReadStreamFromResponse(response);
}
private static string ReadStreamFromResponse(WebResponse response)
{
using (Stream responseStream = response.GetResponseStream())
using (StreamReader sr = new StreamReader(responseStream))
{
string strContent = sr.ReadToEnd();
return strContent;
}
}
private List<string> GetCategoryElements(IEnumerable<XElement> categories)
{
var listOfCategories = new List<string>();
foreach (var category in categories)
{
listOfCategories.Add(category.Value);
}
return listOfCategories;
}
Updated Code from Solution, just added .UnWrap() on the Enqueue method:
var tasks = new Queue<Task>();
foreach (var result in results)
{
tasks.Enqueue(
Task.Factory.StartNew(async ()=>
{
result.Comments = await GetComments(result.CommentUri);
}
).Unwrap());
}
Task.WaitAll(tasks.ToArray());
It is waiting appropriately. The problem is that you are creating a Task which creates another task (i.e. StartNew is returning a Task<Task> and you are only waiting on the outer Task which completes rather quickly (it completes before the inner Task is complete)).
The questions will be:
Do you really want that inner task?
If yes, then you can use Task.Unwrap to get a proxy task that represents the completion of both the inner and outer Task and use that to Wait on.
If no, then you could remove the use of async/await in StartNew so that there is not an inner task (I think this would be prefered, it's not clear why you need the inner task).
Do you really need to do a synchronous Wait on an asynchronous Task? Read some of Stephen Cleary's blog: http://blog.stephencleary.com/2012/02/async-unit-tests-part-1-wrong-way.html
As an aside, if you are not using C# 5, then watch out for closing over the foreach variable result See
Has foreach's use of variables been changed in C# 5?, and
http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx)
In Microsoft.Bcl.Async we couldn't add any static methods to Task. However, you can find most of the methods on TaskEx, for example, TaskEx.WhenAll() does exist.