How to set a property if the value is in another thread - c#

I want set a property where the value is in another thread
[DllExport]
public static bool Value()
{
bool val = false;
Thread thread = new Thread(async () => val = await getVal());
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return val;
}
public async Task<bool> getVal()
{
bool value = false;
await Task.Factory.StartNew(() =>
{
string rs = new WebClient().DownloadString(url);
if (rs == "1")
value = true;
else
value = false;
});
return value;
}
It always returns false why I use that one is I cant use await in a static [DLLExport] method otherwise the form will freeze.
Edit: I cant use async in a DllExport method

Well starting the Thread really tells you nothing about when the code is being run.
After you call .Start() you tell the thread to run its code, but you have no real control of when the OS decides to actually let the code run.
Im also not sure how using locally defined variables inside the other thread-scope actually works, but I find it hard to think that you can set the value like you are trying to do.
Try googling Monitor.Wait(), Monitor.Pulse() which can be used to let one thread wait for another to finish (one calls Monitor.Wait() and the other calls Monitor.Pulse() when it wants the waiting thread to start executing).

Related

Trying to call Start() on a continuation task

I am writing an console application where I want to offload some CPU-bound work onto a new thread in order to keep the main thread responsive. However, I only want to create one new thread at a time; if more CPU-bound work is requested while some is still ongoing, that task should get queued. Here's my implementation:
readonly ConcurrentQueue<Task> _searchQueue = new ConcurrentQueue<Task>();
volatile bool _searchInProgress = false;
var searchTask = new Task(() =>
{
// ... do some cpu-bound work ...
// run the next task if one is queued
if (_searchQueue.TryDequeue(out var nextTask))
{
nextTask.Start();
}
else
{
_searchInProgress = false;
}
});
// *** attempt to propogate exceptions to the main thread ***
searchTask = searchTask.ContinueWith(t =>
{
if (t.IsFaulted) throw t.Exception;
});
if (!_searchInProgress)
{
_searchInProgress = true;
searchTask.Start();
}
else _searchQueue.Enqueue(searchTask);
This code worked fine before I added the ContinueWith clause. After I added it, I got the error:
Start may not be called on a continuation task.
A related SO question says to use Task.Factory.StartNew instead of the Task constructor, but this doesn't work for my use case since I want to create the Task but may not want to immediately start it.

The proper callback from threading mode in c#

I'm using threads to connect to multiple clients (PLCs) from my program. Program will send data and receive response from the PLC(s).. The problem im having is, when in debugging mode, (toggle breakpoint) one step at a time..the program work pretty much ok!, with the ID received confirming that it's coming from one of the thread.. but if I just debug without toggling any breakpoint, the response event will receive the same ID, although on different thread.. what could be wrong...
Debugging mode with breakpoint:
Debugging mode without breakpoint:
Below is my code
Start Request:
private void StartRequest()
{
foreach (ModbusTCP work in works)
{
work.Connect();
Thread.Sleep(1000);
if (work.Connected)
{
try
{
Thread thread = new Thread(new ThreadStart(() => work.StartReadHoldingRegister())) {
Name = ((ReadHoldingRegisterParam)work.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true
};
work.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
work.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
thread.Start();
threads.Add(thread);
}
catch (ThreadStateException ex)
{
MessageBox.Show(ex.Message);
}
}
else
work.Disconnect();
}
}
Response Event
private void modbus_OnResponseEvent(object sender, ModbusTCP.ResponseEventArgs e)
{
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
AddRow(RcvDataGrid, new PLCPacket() {
PLCId = e.id.ToString(),
PLCIp = "Test",
PLCTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt"),
PLCData = ""
});
}));
}
}
}
Your variable work is shared among the threads. Once a thread is executed it takes whatever value your variable work has. That depends how quick each thread is processed. When you step through your code with a debugger you don't experience that.
If you capture the value before the anonymous method you should be fine:
try
{
// capture the current value of the loop variable
ModbusTCP localWork = work;
// so the anonymous method uses the reference in localWork
// instead of whatever value work has, which can be anywhere
// the future, worst case after your loop is finished, where
// work would hold the last value of the loop, and then
// start all threads with that value.
Thread thread = new Thread(
new ThreadStart(
() => localWork.StartReadHoldingRegister()))
{
Name = ((ReadHoldingRegisterParam) localWork.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true };
});
localWork.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
localWork.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
A side comment:
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
This code is very unlikely to be correct. Here you are obtaining a lock in the original thread and then submitting a new action, async. The lock is scoped to the current method, and thus will be released as soon as the BeginInvoke call returns, not during the action itself. The only operations actually guarded by the lock is the e.data.Length check, which operates on a parameter (not shared) state and thus does not need protection.
It would make more sense to place the lock inside the action, but the action is always executed on the main thread and thus is unlikely to actually need protection (because is, basically, single threaded). Is difficult to guess exactly what you're trying to achieve w/o seeing the whole code, but that lock(lockingObject) is very unlikely to be necessary, or useful.

Why does the thread loop infinitely?

I am using VS2010 .Net 4.0, so I cannot use the await calls. I have one thread downloading something, and I shouldn't continue before the status becomes "Done". So I am using a while loop blocking the thread. But somehow it becomes an infinite loop. Am I creating the thread properly?
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
// Loops here forever
while (status != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
}
You need to understand that thread.Join(); blocks in the calling thread until the thread being joined terminates. Once you understand that, you'll see that it is silly to do a while loop in the calling thread on the value of status, as if you've passed the join then the value of status will never change again unless you add code that does so.
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
//no point in looping here, if the thread finished, it has already assigned the
//value it is going to assign to the status variable
if (status == "Done")
{
//do what needs to be done
}
else
{
//uh oh, handle the failure here
}
To address the requirement that you cannot continue until status=="Done", you could instead place your while loop inside the child thread so that it keeps attempting the Download function until it returns "Done":
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
while(status != "Done")
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
//do what needs to be done
Threading can result in some weird stuff sometimes, you need to sometimes tell the compiler that you are preforming something unsafe, you can do that by doing a var nstatus = Volatile.Read( ref status ) and then compare against that.
string nstatus = status;
// Loops here forever
while (nstatus != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
nstatus = Volatile.Read(ref status);
}
Other alternative is to use a Thread.MemoryBarrier() call, (which what I believe is being done in the Volatile call ), which prevents reordering of statements by compiler:
// Loops here forever
while (status != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
Thread.MemoryBarrier();
}
A good resource to look at would be http://www.albahari.com/threading/part4.aspx , very in depth look at threading in .NET 4.0

Change parameters value in a method during its execution in a thread

I would like to know if there is a way to dynamically change the parameters passed to a method when it running in a thread.
For example:
trdColCycl thread = new Thread (() => this.ColorsCycling (true));
trdColCycl.Start();
or
trdColCycl thread = new Thread (new ParameterizedThreadStart (this.ColorsCycling));
trdColCycl.Start(true);
and then I want to pass as a parameter to the thread running the value false ... is it possible?
(in this example I would like to dynamically change the parameter value to exit from a loop inside the thread without using global variables)
Thanks for your help.
You could create a shared variable meant for communicating between two threads
class ArgumentObject
{
public bool isOk;
}
// later
thread1Argument = new ArgumentObject() { isOk = true };
TrdColCycl thread = new Thread (() => this.ColorsCycling (thread1Argument));
trdColCycl.Start();
// much later
thread1Argument.isOk = false;
Edit:
Alternatively, you could pass the bool as reference instead:
bool isOk = true;
TrdColCycl thread = new Thread (() => this.ColorsCycling (ref isOk));
trdColCycl.Start();
// later
isOk = false;
In both cases, you'll have to modify the signature of your method:
// original
void ColorsCycling(bool isOk)
// should be
void ColorsCycling(ArgumentObject argument) // for option 1
// or
void ColorsCycling(ref bool isOk) // for option 2

Quick Multithreading Question

I have a startup function that calls a function which returns a boolean based on whether the set up is successful or not. True if successful, false if failed. I would like to start that function on a new thread and then check the status of the function: here is the code.
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(StartAdapter));
thread.Start();
My question is, how in that case would I check the return status of the startadapter method? Because my friend told me that I will not know the return status because it is started on another thread, and yet trying:
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(StartAdapter));
thread.Start();
bool result = StartAdapter();
would call the function twice, which is something I don't want either. Does anybody have some insight into this?
How in this case would I check the boolean returned from the startadapter function?
.NET 3.5
for this case there is the Task<T> class that executes on the ThreadPool (for example) and lets you know the return value after it's finished
just use:
var task = TaskFactory&ltyourResultType&gt.StartNew(StartAdapter);
Action&ltyourResultType&gt actionAfterResult = ...; // whatever you have to do
task.ContinueWith(actionAfterResult);
// or:
var result = task.Result; // this will block till the result is computed
// or another one of the alternatives you can learn about on MSDN (see link above)

Categories