|
It is impossible to read through all that code.
Where (and what) are you getting the error?
My signature "sucks" today
|
|
|
|
|
I did not read that, it is unreadable without proper formatting; please edit and put the code in a big pair of <PRE> tags.
And provide an explanation: what is it you want? what is happening? what are the symptoms? in what line does it fail?
in summary: please read the "how to get an answer" guidelines near the top of this forum.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
modified on Sunday, May 23, 2010 9:45 AM
|
|
|
|
|
In a class there are private fields and several threads all member of the class.
Does it need to lock read access to class fields to avoid reading only of the class members from several threads at the same time.
Чесноков
|
|
|
|
|
Reading is only a problem if there is a possibility that the value of a field may be changed by another thread during the read. If so, then yes you will need to lock it.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
I've got BackgroundWorker thread in my application which is started in timer event with 10ms interval. It takes about 50ms or larger for a thread to complete. I'm using smaller timer interval to start new thread as soon as possible after previous completed.
I've got IsBusy() method call in timer event to avoid new thread invocation with RunWorkerAsync() if previous is busy by all means.
But in one machine I'm testing it IsBusy fails somehow. Thus before previous thread finished RunWorkerAsync() is called again on the same running Background worker resulting in:
System.InvalidOperationException in Void RunWorkerAsync(System.Object):
Because it is currently too busy, can not perform multiple tasks simultaneously.
How that is possible?
Чесноков
|
|
|
|
|
The IsBusy property is set when you call RunWorkerAsync and isn't unset until immediately before RunWorkerCompleted is raised.
I would start your Timer in your RunWorkerCompleted handler after any other tasks being performed in there so the issue is avoided altogether as there would be no need to check IsBusy at all.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
There is one thread function and an array of BackgrounWorkers.
There might be N workers running on the same thread function.
On every timer event all array memeber are queried for IsBusy to start new worker.
Timer even reset in RunWorkerCompleted will be hard to handle.
I wonder the reason for IsBusy failure if it is set up immediatly after RunWorkerAsync call?
Or it is set up as the thread enters its function?
Чесноков
|
|
|
|
|
When you call RunWorkerAsync ,
1. The IsBusy flag is checked and if true the exception is thrown.
2. The IsBusy flag is set
It is possible that value of IsBusy could be false when you check it (is at position 1) but by the time you call RunWorkerAsync it could be true (position 2) as there is no internal locking on this property. It wouldn't be too hard to create your own with this locking in place.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
RunWorkerAsync is a blocking function. Timer tick event can not return until it finished?
Only if the function is non-blocking it would be possible that a second timer event arrives before previous RunWorkerAsync completed.
The same as in blocking non-blocking windows sockets.
Чесноков
|
|
|
|
|
Only if the Timer is a System.Windows.Forms.Timer and if the BackgroundWorker and Timer were started on the same thread.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Chesnokov Yuriy wrote: Only if the function is non-blocking it would be possible that a second timer event arrives before previous RunWorkerAsync completed.
Nope. A periodic timer is expected to tick, no matter what. See my other reply to you.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I said I didn't think it'd be too hard to sync the IsBusy etc. I hate saying that without knowing for sure so I've knocked up a quick version. This should be OK (untested!), but if using other locks or other synchronisation methods in your other code I'd use the MS one. (Needs comments and descriptions adding)
using System;
using System.ComponentModel;
using System.Threading;
namespace DaveyM69.ComponentModel
{
[DefaultEvent("DoWork")]
[DefaultProperty("WorkerReportsProgress")]
public class SaferBackgroundWorker : Component
{
public event DoWorkEventHandler DoWork;
public event ProgressChangedEventHandler ProgressChanged;
public event RunWorkerCompletedEventHandler RunWorkerCompleted;
private bool cancellationPending;
private bool isBusy;
private AsyncOperation operation;
private SendOrPostCallback operationCompleted;
private SendOrPostCallback progressReporter;
private object syncLock = new object();
private bool workerReportsProgress;
private bool workerSupportsCancellation;
private ParameterizedThreadStart workerThreadStart;
public SaferBackgroundWorker()
{
cancellationPending = false;
isBusy = false;
operation = null;
operationCompleted = new SendOrPostCallback(OperationCompleted);
progressReporter = new SendOrPostCallback(ProgressReporter);
workerReportsProgress = false;
workerSupportsCancellation = false;
workerThreadStart = new ParameterizedThreadStart(WorkerThreadStart);
}
[Browsable(false)]
public bool CancellationPending
{
get { lock (syncLock) { return cancellationPending; } }
}
[Browsable(false)]
public bool IsBusy
{
get { lock (syncLock) { return isBusy; } }
}
[DefaultValue(false)]
public bool WorkerReportsProgress
{
get { lock (syncLock) { return workerReportsProgress; } }
set { lock (syncLock) { workerReportsProgress = value; } }
}
[DefaultValue(false)]
public bool WorkerSupportsCancellation
{
get { lock (syncLock) { return workerSupportsCancellation; } }
set { lock (syncLock) { workerSupportsCancellation = value; } }
}
public void CancelAsync()
{
if (!WorkerSupportsCancellation)
throw new InvalidOperationException("Worker doesn't support cancellation");
SetCancellationPending(true);
}
protected virtual void OnDoWork(DoWorkEventArgs e)
{
DoWorkEventHandler eh = DoWork;
if (eh != null)
eh(this, e);
}
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler eh = ProgressChanged;
if (eh != null)
eh(this, e);
}
protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
{
RunWorkerCompletedEventHandler eh = RunWorkerCompleted;
if (eh != null)
eh(this, e);
}
private void OperationCompleted(object state)
{
SetIsBusy(false);
SetCancellationPending(false);
OnRunWorkerCompleted((RunWorkerCompletedEventArgs)state);
}
private void ProgressReporter(object state)
{
OnProgressChanged((ProgressChangedEventArgs)state);
}
public void ReportProgress(int percentProgress)
{
ReportProgress(percentProgress, null);
}
public void ReportProgress(int percentProgress, object userState)
{
if (!WorkerReportsProgress)
throw new InvalidOperationException("Worker doesn't report progress");
ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
if (operation == null)
progressReporter(arg);
else
operation.Post(progressReporter, arg);
}
public void RunWorkerAsync()
{
RunWorkerAsync(null);
}
public void RunWorkerAsync(object argument)
{
if (IsBusy)
throw new InvalidOperationException("Worker is busy");
SetIsBusy(true);
SetCancellationPending(false);
operation = AsyncOperationManager.CreateOperation(null);
workerThreadStart.BeginInvoke(argument, null, null);
}
private void SetCancellationPending(bool value)
{
lock (syncLock) { cancellationPending = value; }
}
private void SetIsBusy(bool value)
{
lock (syncLock) { isBusy = value; }
}
private void WorkerThreadStart(object obj)
{
object result = null;
Exception error = null;
bool cancelled = false;
try
{
DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(obj);
OnDoWork(doWorkArgs);
if (doWorkArgs.Cancel)
cancelled = true;
else
result = doWorkArgs.Result;
}
catch (Exception exception)
{
error = exception;
}
RunWorkerCompletedEventArgs e = new RunWorkerCompletedEventArgs(result, error, cancelled);
operation.PostOperationCompleted(operationCompleted, e);
}
}
}
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Hi,
I'm not sure what it is you are trying, but it sure sounds like you are having synchronization problems.
Some comments:
1.
As usual, MSDN says: "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
So if you have several threads interested in a single BGW, you'll need some synchronization.
2.
the GUI magic of a BGW (i.e. accessing the GUI safely from within the ProgressChanged or RunWorkerCompleted events) only works if the BGW got created by the main thread.
3.
as (almost) all event handlers, the first parameter in ProgressChanged or RunWorkerCompleted identifies the BGW itself. So it should be rather easy to share a Progress or Completed handler amongst multiple BGWs.
4.
if you want to pass several jobs to the same BGW, to be executed in sequence, why not use a queue (with a lock!), and have DoWork fetch its jobs from that queue?
5.
which timer class are you using? only System.Windows.Forms.Timer ticks on the main thread; the others tend to tick on a ThreadPool thread.
6.
Windows timers have limited resolution; you mentioned 10msec and shorter; not sure you are getting those. Have a read of this: Timer surprises, and how to avoid them[^]
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
There is windows service application that should access some network resource and get data from it (e.g. SQL server, network server with some files, etc...)
There might be N such threads running in parallel each connecting to its own resource. Thus there are N instances of the helper class (performing such remote data collection) in the List array in the instance field of the service.
4. They need to run in parallel not in sequence one after another.
5. Timer is System.Threading.Timer. I'm using logging with milliseconds marks and can confirm accuracy depending on cpu load.
That is the timer tick function:
for (int i = 0; i < this.drives.Count; i++)
{
if (this.drvBackgroundWorkers[i].IsBusy == false)
{
BackgroundWorkerArgument argument = new BackgroundWorkerArgument()
{
threadId = i,
drive = this.drives[i]
};
this.drvBackgroundWorkers[i].RunWorkerAsync(argument);
}
}
drvBackgroundWorkers is not accessed in any thread code only in that tick function.
I wonder the reason for a failure??
Чесноков
|
|
|
|
|
1.
first of all, when a System.Threading.Timer ticks, its handler runs on an arbitrary ThreadPool thread, not on the thread that did start your BGW, and not on the thread that may be executing the current job of your BGW. And the BGW itself needs to access IsBusy() too. So there are several threads involved in accessing the one property.
2.
timer handler executions may overlap, i.e. a second one could start before the first one has finished. Here is proof, run it in debug mode and watch the times, and the counts:
System.Threading.Timer timer;
int count;
public override void Test(int arg) {
timer=new System.Threading.Timer(new TimerCallback(ticker), null, 30, 30);
}
protected void output(string s) {
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ")+s);
}
public void ticker(object dummy) {
output("ticker("+count+") start");
for (int i=0; i<10000000; i++) { }
output("ticker("+count+") stop");
count++;
if (count>10) {
timer.Change(Timeout.Infinite, Timeout.Infinite);
output("done");
}
}
[ADDED]
I only tested on a dual-core, however I don't think it needs a multi-core for overlaps to occur.
[/ADDED]
One way to fix it, would be to make the timer single-shot; and fire it again (using Change) when its handler is done.
3.
you are trying to feed new jobs to existing BGW. The easy way out would be to create a new BGW each time; yes, that is more expensive.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
modified on Sunday, May 23, 2010 11:18 AM
|
|
|
|
|
Hi all,
I have a DataGridView where the user can change the columns widths (by dragging the column header divider). However, I'd like to disable the functionality that double-clicking the column header divider auto-resizes the column with. I tried using the ColumnDividerDoubleClick event to handle this event manually, but the column width still automatically resizes.
Ideas?
Thanks!
Eyal.
|
|
|
|
|
|
It is a Sunday, so most of Europe is not at work.
It is also sunny and hot in the UK, so most people are out in the fresh air, warming and drying out after a long cold winter. Some are trying to work out what that big, hot, yellow thing up there is, since we haven't seen it for a couple of years...
Normal service will resume tomorrow. Probably.
If the warm weather doesn't encourage too much beer drinking, with resulting spontaneous-Monday-morning-illness problems. It might.
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
Hello did you found any answer for this?
Thanks.
|
|
|
|
|
Hi
I'm new in C#.net. I have been facing a problem for so many days but couldn't solve it yet.
Can anybody help me how can server get the ip address of connected client in c#?
i am using following code:
Socket rsock = m_workerSocket[m_clientCount];
textBox2.Text =
((IPEndPoint)rsock.RemoteEndPoint).Address.ToString();
but instead of getting client address i always get server ip address.
can anybody help me to sort out this problem?
|
|
|
|
|
Try IpEndPoint ipend = rsock.Client.RemoteEndPoint; .
My signature "sucks" today
|
|
|
|
|
hi
thanxs fo ur rply
but Im facing the same problem with this code.
now what shud i do?
thanx
|
|
|
|
|
Please read How to get an answer to your question[^]
Plz help me is not an appropriate subject. You have not formatted the code posted. If you want serious responses, then follow these guidelines.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
hi
thanx 4 ur guidance.i want to get ip address of client on server side but remote end property does not work in this context.
thanx.
|
|
|
|
|
I have program develop using C# 2008 with access database 2003. How to include this database in installer?..I build Installer Using Publish..
|
|
|
|