What I need to do is be able to cancel a task that is running async.
I have been searching and cannot seem to wrap my head around it. I just cant seem to discern how it would be implemented into my current setup.
Here is my code that fires my task off. Any help on where or how to implement a cancellation token would be greatly appreciated.
private async void startThread()
{
//do ui stuff before starting
ProgressLabel.Text = String.Format("0 / {0} Runs Completed", index.Count());
ProgressBar.Maximum = index.Count();
await ExecuteProcesses();
//sort list of output lines
outputList = outputList.OrderBy(o => o.RunNumber).ToList();
foreach (Output o in outputList)
{
string outStr = o.RunNumber + "," + o.Index;
foreach (double oV in o.Values)
{
outStr += String.Format(",{0}", oV);
}
outputStrings.Add(outStr);
}
string[] csvOut = outputStrings.ToArray();
File.WriteAllLines(settings.OutputFile, csvOut);
//do ui stuff after completing.
ProgressLabel.Text = index.Count() + " runs completed. Output written to file test.csv";
}
private async Task ExecuteProcesses()
{
await Task.Factory.StartNew(() =>
{
int myCount = 0;
int maxRuns = index.Count();
List<string> myStrings = index;
Parallel.ForEach(myStrings,
new ParallelOptions()
{
MaxDegreeOfParallelism = settings.ConcurrentRuns
}, (s) =>
{
//This line gives us our run count.
int myIndex = myStrings.IndexOf(s) + 1;
string newInputFile = Path.Combine(settings.ProjectPath + "files/", Path.GetFileNameWithoutExtension(settings.InputFile) + "." + s + ".inp");
string newRptFile = Path.Combine(settings.ProjectPath + "files/", Path.GetFileNameWithoutExtension(settings.InputFile) + "." + s + ".rpt");
try
{
//load in contents of input file
string[] allLines = File.ReadAllLines(Path.Combine(settings.ProjectPath, settings.InputFile));
string[] indexSplit = s.Split('.');
//change parameters here
int count = 0;
foreach (OptiFile oF in Files)
{
int i = Int32.Parse(indexSplit[count]);
foreach (OptiParam oP in oF.Parameters)
{
string line = allLines[oP.LineNum - 1];
if (oP.DecimalPts == 0)
{
string sExpression = oP.Value;
sExpression = sExpression.Replace("%i", i.ToString());
EqCompiler oCompiler = new EqCompiler(sExpression, true);
oCompiler.Compile();
int iValue = (int)oCompiler.Calculate();
allLines[oP.LineNum - 1] = line.Substring(0, oP.ColumnNum - 1) + iValue.ToString() + line.Substring(oP.ColumnNum + oP.Length);
}
else
{
string sExpression = oP.Value;
sExpression = sExpression.Replace("%i", i.ToString());
EqCompiler oCompiler = new EqCompiler(sExpression, true);
oCompiler.Compile();
double dValue = oCompiler.Calculate();
dValue = Math.Round(dValue, oP.DecimalPts);
allLines[oP.LineNum - 1] = line.Substring(0, oP.ColumnNum - 1) + dValue.ToString() + line.Substring(oP.ColumnNum + oP.Length);
}
}
count++;
}
//write new input file here
File.WriteAllLines(newInputFile, allLines);
}
catch (IOException ex)
{
MessageBox.Show(ex.ToString());
}
var process = new Process();
process.StartInfo = new ProcessStartInfo("swmm5.exe", newInputFile + " " + newRptFile);
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit();
Output output = new Output();
output.RunNumber = myIndex;
output.Index = s;
output.Values = new List<double>();
foreach(OutputValue oV in OutputValues) {
output.Values.Add(oV.getValue(newRptFile));
}
outputList.Add(output);
//get rid of files after run
File.Delete(newInputFile);
File.Delete(newRptFile);
myCount++;
ProgressBar.BeginInvoke(
new Action(() =>
{
ProgressBar.Value = myCount;
}
));
ProgressLabel.BeginInvoke(
new Action(() =>
{
ProgressLabel.Text = String.Format("{0} / {1} Runs Completed", myCount, maxRuns);
}
));
});
});
}
The best way to support cancellation is to pass a CancellationToken to the async method. The button press can then be tied to cancelling the token
class TheClass
{
CancellationTokenSource m_source;
void StartThread() {
m_source = new CancellationTokenSource;
StartThread(m_source.Token);
}
private async void StartThread(CancellationToken token) {
...
}
private void OnCancelClicked(object sender, EventArgs e) {
m_source.Cancel();
}
}
This isn't quite enough though. Both the startThread and StartProcess methods will need to be updated to cooperatively cancel the task once the CancellationToken registers as cancelled
Related
I would like to ask, How I can use the While statement for downloading URL?
Here's what I want to happen.
I want to check if the url from CheckBoxListItems is already exist from my ListView
There's a case that I'm adding another urls to my listbox and I don't want to download again.
if url is already exists in my listview it will skip and proceed to the next url(which is not yet downloaded).
Here's my current codes:
int count = 0;
int total = LB.CheckedItems.Count;
string counter = string.Empty;
using (cts = new CancellationTokenSource())
{
try
{
if (cts.IsCancellationRequested) { throw new TaskCanceledException(); }
txtOutput.Text = string.Empty;
Cursor = Cursors.WaitCursor;
Parsing = true;
Text = "Getting links information. Please wait...";
foreach (string url in LB.CheckedItems)
{
var info = await Task.Run(() => Parser.GetJsonData(url, cts.Token));
count++;
counter = "( " + count + " of " + total + " )";
lblTotalLinks.Text = counter;
Text = "Parsing in progress. Please wait... " + counter;
AddToListView(info); //ADD DOWNLOADED STRINGS TO LISTVIEW
}
Text = "Parsing done. " + counter;
}
catch (OperationCanceledException ex)
{ Text = ex.Message; }
catch (Exception ex)
{ MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
Parsing = false;
Cursor = Cursors.Default;
cts = null;
//ADD TO LISTVIEW()
private void AddToListView(MediaInfo info)
{
int count = LV.Items.Count + 1;
var results = new List<ListViewItem> { new ListViewItem(new[]
{
count.ToString(),
info.Series,
"Episode " + info.Episode,
info.Title,
info.Runtime,
info.Resolution,
info.Category,
info.URL, //here's what I want to check if already exists
info.M3u8_url,
info.FileSize,
info.Fragments
})};
ListViewItem[] array = results.ToArray();
LV.BeginUpdate();
LV.ListViewItemSorter = null;
LV.Items.AddRange(array);
LV.Focus();
LV.EndUpdate();
Countlists();
LV.Items[LV.Items.Count - 1].EnsureVisible();
}
this is the example of what I want:
string urlExists = string.Empty;
foreach (ListViewItem item in LV.Items)
{
urlExists = item.SubItems[7].Text;
foreach (string url in LB.CheckedItems)
{
while (url != urlExists)
{
}
}
I have a small issue when trying to append text from a loop into a stringbuilder, after trying a few things out, i think i'm on the right track with this.
Code:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// STRING VALUE IT SO WE CAN REUSE //
string action = e.Argument as string;
// CONNECTION //
if (action == "wraith_create_project")
{
// STRING BUILDER //
StringBuilder sb = new StringBuilder();
// VARS //
var articleSource = "";
// INVOKE - AVOID CROSS THREAD ERRORS //
Invoke(new MethodInvoker(() => { articleSource = comboBoxArticleSources.Text; }));
// TRY/CATCH //
try
{
// INVOKE - AVOID CROSS THREAD ERRORS //
Invoke(new MethodInvoker(() => { listBoxMain.Items.Add("[" + DateTime.Now + "] Creating project ... " + txtBoxProjectName.Text); }));
// ARTICLE SOURCE //
if (articleSource == "Internal Article Builder")
{
// VARS/CONSTANTS //
var separator = Environment.NewLine;
const string gsaSeparator = "\x01";
// WHICH SPINNER TO USE //
if (chkBoxInternalSpinner.Checked) {
// LOOP //
var title = "";
var body = "";
var hash = "";
//var gsaArticleInfo = "";
for (int x = 0; x <= 5; x++ ) {
// EVERY LOOP REQUESTS AN ARTICLE //
var requestArticles = Helpers.getArticleTitleAndBodyInternalSpinner("https://www.wraithseo.com/api.php?articleBuilder=1&q=" + txtBoxScrapeKeyword.Text.Replace(" ", "_"));
title = Helpers.internalSpinner(requestArticles.Item1); // SEND TO INTERNAL SPINNER FOR SPINNING ...
body = Helpers.internalSpinner(requestArticles.Item2); // SEND TO INTERNAL SPINNER FOR SPINNING ...
hash = To32BitFnv1aHash(body).ToString("X8");
Invoke(new MethodInvoker(() =>
{
listBoxMain.Items.Add("[" + DateTime.Now + "] Returned article ... " + requestArticles.Item1);
listBoxMain.Items.Add("[" + DateTime.Now + "] Spun the article ... " + title);
}));
// ENCODE WITH THE GSA SEPERATOR BETWEEN EACH FIELD //
var gsaArticleInfo = title + gsaSeparator + "%first_paragraph-article%" + gsaSeparator + body + gsaSeparator + hash;
// ADD TO THE RICHTEXTBOX ALL FIELDS FROM ABOVE //
var richTextBoxText = string.Join(separator, gsaArticleInfo);
// APPEND FIELDS TO THE STRINGBUILDER //
sb.Append(richTextBoxText);
}
// INVOKE - AVOID CROSS THREAD ERRORS //
Invoke(new MethodInvoker(() => { richTxtBoxArticle.Text = sb.ToString(); }));
}
} else if (articleSource == "") {
// RESERVED FOR ADDITIONAL SOURCES //
}
} catch (Exception ex) {
Helpers.returnMessage(ex.ToString());
}
}
}
What i'm doing here is sending a request to my server which is returning an article sized bunch of text, i'm then spinning that text and trying to display it in a richTextBox, i noticed that instead of adding each article to the richTextBox it was being overwritten by the same article, i thought by using the stringbuilder to append the article to it on each loop i could then display it outside the loop but it always seems to overwrite, instead of adding 5 articles (which is the max i have set for tetsing)
Any help would be appreciated.
Updated Code:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
string action = e.Argument as string;
if (action == "wraith_create_project")
{
StringBuilder sb = new StringBuilder();
var separator = Environment.NewLine;
const string gsaSeparator = "\x01";
var articleSource = "";
var title = "";
var body = "";
var hash = "";
var gsaArticleInfo = "";
var richTextBoxText = "";
// TEST //
List<string> gsaStuff = new List<string>();
// TEST //
Invoke(new MethodInvoker(() => { articleSource = comboBoxArticleSources.Text; }));
try
{
Invoke(new MethodInvoker(() => { listBoxMain.Items.Add("[" + DateTime.Now + "] Creating project ... " + txtBoxProjectName.Text); }));
if (articleSource == "Internal Article Builder")
{
if (chkBoxInternalSpinner.Checked) {
for (int x = 0; x <= 5; x++ ) {
// EVERY LOOP REQUESTS AN ARTICLE WHICH IS RETURNED AT RAND() //
var requestArticles = Helpers.getArticleTitleAndBodyInternalSpinner("https://www.wraithseo.com/api.php?articleBuilder=1&q=" + txtBoxScrapeKeyword.Text.Replace(" ", "_"));
title = Helpers.internalSpinner(requestArticles.Item1); // SEND TO INTERNAL SPINNER FOR SPINNING ...
body = Helpers.internalSpinner(requestArticles.Item2); // SEND TO INTERNAL SPINNER FOR SPINNING ...
hash = To32BitFnv1aHash(body).ToString("X8");
Invoke(new MethodInvoker(() =>
{
listBoxMain.Items.Add("[" + DateTime.Now + "] Returned article ... " + requestArticles.Item1);
listBoxMain.Items.Add("[" + DateTime.Now + "] Spun the article ... " + title);
}));
// ENCODE WITH THE GSA SEPERATOR BETWEEN EACH FIELD //
gsaArticleInfo = title + gsaSeparator + "%first_paragraph-article%" + gsaSeparator + body + gsaSeparator + hash;
// ADD TO THE RICHTEXTBOX ALL FIELDS FROM ABOVE //
richTextBoxText = string.Join(separator, gsaArticleInfo);
// APPEND FIELDS TO THE STRINGBUILDER //
sb.Append(string.Join(separator, gsaArticleInfo));
gsaStuff.Add(richTextBoxText);
// INVOKE - AVOID CROSS THREAD ERRORS //
Invoke(new MethodInvoker(() => { richTxtBoxArticle.AppendText(richTextBoxText); }));
Invoke(new MethodInvoker(() => { richTxtBoxArticle.Lines = gsaStuff.ToArray(); }));
} // End for loop.
Invoke(new MethodInvoker(() => { richTxtBoxArticle.Lines = gsaStuff.ToArray(); }));
//Helpers.returnMessage("SB Contents: > " + sb.ToString());
} // End checkbox.
} else if (articleSource == "") {
// RESERVED FOR ADDITIONAL SOURCES //
}
} catch (Exception ex) {
Helpers.returnMessage(ex.ToString());
}
}
}
This is happening because you're calling onto the UI thread from another thread REALLY QUICKLY. The textbox simply can't keep up.
The solution here is to use the BackgroundWorker.ReportProgress method, and pass the strings back out of your worker to your UI thread. You'd handle the ProgressChanged event of the worker from your Form, and update your controls within there instead.
Hope that helps you out.
I have a windows service,the codes in that body are in a elapsed timer method. I call some web services in a loop,that those web services run in a thread.
I checked the services on servers, they dont start.
And when I take out the codes from thread body,those worked.
This is my windows service code that calls webservices from servers.
private void CallServiceForTrancoding(object sender, System.Timers.ElapsedEventArgs e)
{
DataSet.TranscodingVideosDataTable oTranscodingVideosDataTable = new DataSet.TranscodingVideosDataTable();
DataSetTableAdapters.TranscodingVideoTableAdapter oTranscodingVideoTableAdapter = new DataSetTableAdapters.TranscodingVideoTableAdapter();
oTranscodingVideoTableAdapter.FillVideosForTranscoding(oTranscodingVideosDataTable);
DataSet.ServersDataTable oServersDataTable = new DataSet.ServersDataTable();
DataSetTableAdapters.ServersTableAdapter oServersTableAdapter = new DataSetTableAdapters.ServersTableAdapter();
oServersTableAdapter.FillBaseOnConvertAction(oServersDataTable);
for (int i = 0; i < oTranscodingVideosDataTable.Count; i++)
{
if (oTranscodingVideosDataTable[i].IsQualityNull() == false)
{
var Qualities = oTranscodingVideosDataTable[i].Quality.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
string path = oTranscodingVideosDataTable[i].Path + oTranscodingVideosDataTable[i].ObjectUniqueName;
string[] Url = new string[Qualities.Length];
for (int j = 0; j < Qualities.Length; j++)
{
if (j == 0)
{
Url[j] = path;
}
else
{
Url[j] = path.Replace(path.Split('/').Last(), "") + path.Split('/').Last().Split('.')[0] + "-" + Qualities[j] + "." + path.Split('/').Last().Split('.')[1];
}
}
string parameters = "Token=" + "#HelloWorld" +
"&Url=" + new JavaScriptSerializer().Serialize(Url) +
"&FileUniqueName=" + oTranscodingVideosDataTable[i].ObjectUniqueName +
"&ip=" + oTranscodingVideosDataTable[i].IPValid +
"&GregoreanDate=" + oTranscodingVideosDataTable[i].Gorean_Date.ToString();
DataSet.VideoDataTable oVideoDataTable = new DataSet.VideoDataTable();
DataSetTableAdapters.VideoTableAdapter oVideoTableAdapter = new DataSetTableAdapters.VideoTableAdapter();
oVideoTableAdapter.UpdateVideoStatus(oTranscodingVideosDataTable[i].ObjectUniqueName);
string WebServiceOfServer = oServersDataTable[i].WebService;
WebServiceOfServer = WebServiceOfServer.Replace(WebServiceOfServer.Split('/').Last(), "RS");
JavaScriptSerializer objSerializer = new JavaScriptSerializer();
//Task a = Task.Factory.StartNew(() => {
Task ResponseResult = GetPostMethods.POST(WebServiceOfServer, parameters);
string JSONResult = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ResponseResult);
var ResponseString = objSerializer.Deserialize<dynamic>(JSONResult);
var UserToken = ResponseString["Result"]["UserToken"];
var Successfully = ResponseString["Result"]["Successfully"];
//});
}
}
}
Here is my web method :
[WebMethod]
public void RS(string Token, string Url, string FileUniqueName, string ip,string GregoreanDate)
{
new Thread(() =>
{
if (Token != "HelloWorld")
{
}
else
{
try
{
var VideoUrl = new JavaScriptSerializer().Deserialize<string[]>(Url);
string[] FileName = new string[VideoUrl.Length];
string[] FilePath = new string[VideoUrl.Length];
t.VideoUniqueName = FileUniqueName.Split('.')[0];
t.mediaOutPath = HttpContext.Current.Server.MapPath("/video/") + DateTime.Parse(GregoreanDate).Year + "\\" + DateTime.Parse(GregoreanDate).Month + "\\" + FileUniqueName.Split('.')[0] + "\\";
t.mediaOutFolderPath = "/video/" + DateTime.Parse(GregoreanDate).Year + "/" + DateTime.Parse(GregoreanDate).Month + "/";
if (!Directory.Exists(t.mediaOutPath))
{
Directory.CreateDirectory(t.mediaOutPath);
Directory.CreateDirectory(t.mediaOutPath + "m3u8\\");
}
t.CreateFTPPathForVideoScheduler(t.VideoTypeFormKey, t.mediaOutPath);
string Paths = "";
for (int i = 0; i < VideoUrl.Length; i++)
{
FileName[i] = VideoUrl[i].Split('/').Last();
if (FileName[i] != FileUniqueName)
{
FilePath[i] = t.mediaOutPath + FileName[i];
}
else
{
FilePath[i] = t.ffmpegFolderPath + FileName[i];
}
using (WebClient client = new WebClientWithAwesomeTimeouts { Timeout = new TimeSpan(10, 0, 0, 0) })
{
try
{
client.DownloadFile(VideoUrl[i], FilePath[i]);
client.Dispose();
}
catch (Exception ex)
{
StreamWriter sw = new StreamWriter(t.LogPath, true);
sw.WriteLine(ex.Message + "----" + ex.StackTrace != null ? ex.StackTrace : "" + "----" + DateTime.Now);
sw.Close();
}
}
}
DirectoryInfo FilesDirectory = new DirectoryInfo(t.ffmpegFolderPath);
FileInfo[] fInfo = FilesDirectory.GetFiles("*" + FileUniqueName.Split('.')[0] + "*.*");
fInfo[0].CopyTo(t.mediaOutPath + FileUniqueName, true);
t.SendFileWithFTPScheduler(t.VideoTypeFormKey, t.mediaOutPath + FileUniqueName);
FilesDirectory = new DirectoryInfo(t.mediaOutPath);
fInfo = FilesDirectory.GetFiles("*" + FileUniqueName.Split('.')[0] + "*.*");
foreach (FileInfo file in fInfo)
{
t.SendFileWithFTPScheduler(t.VideoTypeFormKey, file.FullName);
}
string UniqueFilePath = FilePath[0].Replace(FilePath[0].Split('/').Last(), FileUniqueName);
JavaScriptSerializer objSerializer = new JavaScriptSerializer();
var VideoDimensions = objSerializer.Deserialize<Dictionary<string, string>>(t.getVideoHeightAndWidth(t.ffmpegFolderPath + UniqueFilePath));
string Width = VideoDimensions["Width"];
string Height = VideoDimensions["Height"];
Transcoding.VideoResolutions vr = new Transcoding.VideoResolutions();
var VideoResolutionsInfo = objSerializer.Deserialize<Dictionary<object, object>>(t.getVideoResolution(Height));
vr.OrginalResolution = VideoResolutionsInfo["OrginalResolution"].ToString();
vr.ResCount = Convert.ToInt32(VideoResolutionsInfo["ResCount"]);
vr.OrginalResIndex = Convert.ToInt32(VideoResolutionsInfo["OrginalResIndex"]);
vr.UpperResolutionHeight = VideoResolutionsInfo["UpperResolutionHeight"].ToString();
t.MakeM3U8FormatScheduler(FileUniqueName, vr.OrginalResolution, vr.ResCount, vr.OrginalResIndex, false, "", Height);
t.ProcessFilesScheduler(t.mediaOutPath + "m3u8\\", t.VideoTypeFormKey);
DataSet.VideoDataTable oVideoDataTable = new DataSet.VideoDataTable();
DataSetTableAdapters.VideoTableAdapter oVideoTableAdapter = new DataSetTableAdapters.VideoTableAdapter();
oVideoTableAdapter.UpdateVideoForAcceptation(1, true, "mp4,m3u8", "http://" + t.mediaOutFolderPath + t.VideoUniqueName + "/", FileUniqueName);
oVideoTableAdapter.UpdateStatus("resfinish", FileUniqueName);
foreach (string path in VideoUrl)
{
if (path.ToLower().Contains("mp4videos"))
{
t.FTPDelete(new Uri(path.Replace(new Uri(path).Host, ip).Replace("http", "ftp")));
}
}
System.IO.File.Delete(t.ffmpegFolderPath + UniqueFilePath);
System.IO.Directory.Delete(t.mediaOutPath, true);
}
catch (Exception ex)
{
}
}
}).Start();
}
Task ResponseResult = GetPostMethods.POST(WebServiceOfServer, parameters);
string JSONResult = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ResponseResult);
You are serializing a task. You surely want to wait for the result, don't you?
I debugged my web service and I found that the issue is related to httpcontext.current in thread is null .
For that I defined HttpContext.Current.Server.MapPath("/video/") as a variable in a class and I recalled it from the webservice.
So I have a foreach loop that goes through a DataGridView. For each row in the grid it executes a pspasswrd.exe and changes the password of a local account. How can I pause the foreach loop until the process completes before moving onto the next computer in the list?
I am not sure, I tried WaitForExit but this is not reliable since it is synchronous so it cause my program to not respond if it takes a long time. I need to utilize Process.Exited but unsure how to do this correctly.
Here is my foreach loop. Which also checks if the password was changed successfully. And inputs data into another Datagridview if it was success.
foreach (DataGridViewRow row in dgvData.Rows)
{
if (!row.IsNewRow && row.Cells["cIPAddress"].Value.ToString().Contains("Invalid") == false)
{
if (pspasswrd(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword).Contains("Password successfully changed"))
{
dgvResults.Rows.Add(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword);
AppendNumber = AppendNumber + IncreaseNumber;
NewPassword = BasePassword + AppendNumber;
}
else
row.DefaultCellStyle.BackColor = Color.Red;
}
Thread.Sleep(1000);
}
But what I am unsure is that if I change my code below to use process.exited. How will it associate the password change to the computer it was successfully on. As it will be asynchronous.
public string pspasswrd(string ip, string user, string password)
{
String CD = #Directory.GetCurrentDirectory() + "\\pspasswrd.exe";
ProcessStartInfo p = new ProcessStartInfo();
string result = null;
p.FileName = CD;
p.Arguments = #"\\" + ip + " " + user + " " + password + " -accepteula";
p.CreateNoWindow = true;
p.RedirectStandardOutput = true;
p.RedirectStandardError = true;
p.UseShellExecute = false;
Process x = Process.Start(p);
StreamReader stream = x.StandardOutput;
result = stream.ReadToEnd();
x.WaitForExit(2000);
x.Close();
return result;
}
You should first collect all the needed information from DataGridView in a collection then run your code for executing pspasswrd.exe in a background thread looping on the collection instead of DataGridView and use WaitForExit, this will not block your UI thread.
EDIT
Here is the code with WaitForExit and a new thread. I believe that you will not gain much using the Exit event instead of WaitForExit other then much more complexity and deadlock scenarios:
private void OnSomeUIEvent()
{
//In UI thread
var ipRows = new Dictionary<string, DataGridViewRow>();
var targetUser = ""; //tbTargetUser.Text
var pwd = ""; //NewPassword
var basePassword = ""; //Some value
foreach (DataGridViewRow row in dgvData.Rows)
{
var ipAddress = row.Cells["cIPAddress"].Value.ToString();
if (!row.IsNewRow && ipAddress.Contains("Invalid") == false)
{
ipRows.Add(ipAddress, row);
}
}
Task.Factory.StartNew(() => {
ChangePassword(ipRows, targetUser, pwd, basePassword);
}).ContinueWith(t => {
//Do Something when task completed
});
}
private void ChangePassword(Dictionary<string, DataGridViewRow> ipRows, string targetUser, string newPwd, string basePwd)
{ //in background thread
foreach (var ipRow in ipRows)
{
var pwd = newPwd;
var basePassword = basePwd;
var appendNumber = 0;
var increaseNumber = 1; //some number
if (pspasswrd(ipRow.Key, targetUser, pwd).Contains("Password successfully changed"))
{
dgvResults.Invoke((MethodInvoker)(() =>
{
dgvResults.Rows.Add(ipRow.Key, targetUser, pwd);
}));
appendNumber = appendNumber + increaseNumber;
pwd = basePassword + increaseNumber;
}
else
{
dgvData.Invoke((MethodInvoker)(() =>
{
ipRow.Value.DefaultCellStyle.BackColor = Color.Red;
}));
}
}
}
I am trying to run the thread to fetch the result simultaneously from the network on the basis of the query. Below is my code for thread calling
for(int i=0;i<numberOfConnection;i++)
{
//threadResult[i] = onListen(s[i], toquery);
exec[i] = new Thread(() => threadResult[i] = onListen(s[i], toquery));
exec[i].Start();
}
and onListen function is
private string onListen(Socket s,string query)
{
string returnmsg = DateTime.Now.ToString("HH:mm:ss.ffff tt"); //= Start Time ===
try
{
Stream ss = new NetworkStream(s);
StreamReader sr = new StreamReader(ss);
StreamWriter sw = new StreamWriter(ss);
sw.AutoFlush = true;
sw.WriteLine(query);
returnmsg += " " + sr.ReadLine() + " " + DateTime.Now.ToString("HH:mm:ss.ffff tt"); //== End Time ==
s.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return returnmsg;
}
But I am getting error of index out of range exception.
If I run the same code without using thread like this
threadResult[i] = onListen(s[i], toquery);
it works. Kindly help me tracking the bug.
Try this:
for(int i=0;i<numberOfConnection - 1;i++)
{
//threadResult[i] = onListen(s[i], toquery);
exec[i] = new Thread(() => threadResult[i] = onListen(s[i], toquery));
exec[i].Start();
}
Or
for(int i=1;i<numberOfConnection;i++)
{
//threadResult[i] = onListen(s[i], toquery);
exec[i] = new Thread(() => threadResult[i] = onListen(s[i], toquery));
exec[i].Start();
}