|
I have a method that polls different containers of items that are varying in length.
I'd like to divide the container item total count by pages with 1000 items per page, create a new list for each 1000 item page and then spawn a new thread for each page to process the 1000 items asynchronously.
I'm not sure how to create a dynamically named list though? Thanks
|
|
|
|
|
I think to assist you with this we'd need to know some specifics about what "containers of items" are, and what type/structure/format data the results of the "polling" returns.
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
|
|
|
|
|
Hi,
They are active directory computer objects.
I've typed them into strings from DirectoryServices.SearchResult to an all encompassing list<string> and I'd like to divide them up from that point.
|
|
|
|
|
What is stopping you at this point from creating a List<List<string>> with any arbitrary name and using that ?
private List<List<string>> bunchOData = new List<List<string>>();
private const int ChunkSize = 1000;
private void MakeData()
{
List<string> bigData = new List<string>();
for (int i = 0; i < 23678; i++) bigData.Add("x");
int limit = (bigData.Count / ChunkSize) * ChunkSize;
int finalChunk = bigData.Count - limit;
for (int i = 0; i < limit; i += ChunkSize)
{
bunchOData.Add(bigData.GetRange(i, ChunkSize));
}
bunchOData.Add(bigData.GetRange(limit, finalGulp));
} While GetRange makes a shallow copy (references), the fact you are dealing with strings here makes me wonder about memory usage, particularly when you pass the List<string> items in 'bunchOData into separate threads. If you active-directory-whatever objects turned-into-strings are of varying lengths, then I don't think there's much you can do to avoid getting lots of string being created.
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
|
|
|
|
|
I did not know you could do that, although I had always wondered how you could fit an array into an array. Thank you for that example, that worked well.
After that bunchOData is populated, I'm trying to start a thread utilizing each 1000 page chunk of data, how can I pass the 1000 page chunk into a new thread? There will be multiple threads going with each 1000 page chunk with my loop and I'd like each thread to return a sorted list<string> itself. Can I pass an unfiltered list to the thread and return a filtered list when the thread is done?
foreach (List<string> data in bunchOData )
{
var t = new Thread(() => searcher(computerNameArray, sidToSearchFor));
t.IsBackground = true;
t.Start();
}
private List<string> searcher(List<string> computerNames, string sidToSearchFor)
{
List<string> returnValue = null;
//do stuff here
return returnValue;
}
modified 2-Feb-15 10:39am.
|
|
|
|
|
Why would you want to name them at all? Just dynamically create the list as usual, and pass it as a parameter to the thread.
The tread constructor has an overload taking a ParameterizedThreadStart - MSDN[^] - allowing you to pass a single parameter as an object to the thread. Pass the newly created List, and cast it back in the thread.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
I believe I'm trying to do this very thing but having trouble passing an unfiltered list to the parameterized thread start function and then returning a filtered list from that parameterized thread start.
foreach (List<string> computerNameArray in computerNamesArray)
{
var t = new Thread(() => searcher(computerNameArray, sidToSearchFor));
t.IsBackground = true;
t.Start();
}
private List<string> searcher(List<string> computerNames, string sidToSearchFor)
{
List<string> returnValue = null;
//do stuff here
return returnValue;
}
modified 2-Feb-15 10:40am.
|
|
|
|
|
Passing a value into a Thread is pretty easy:
Thread t = new Thread(DoWork);
t.Start("hello there");
}
private void DoWork(object o)
{
string s = o as string;
if (s != null)
{
Console.WriteLine(s);
}
}
Getting a return value is a lot harder!
If I needed a return value, I'd probably do it via a BackgroundWorker instead of a Thread, because that makes it really easy:
BackgroundWorker work = new BackgroundWorker();
work.DoWork += work_DoWork;
work.RunWorkerCompleted += work_RunWorkerCompleted;
work.RunWorkerAsync("hello There");
}
private void work_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine(e.Result);
}
private void work_DoWork(object sender, DoWorkEventArgs e)
{
string s = e.Argument as string;
if (s != null)
{
Console.WriteLine(s);
}
e.Result = string.Format("{0}: Complete", e.Argument);
}
Because Argument and Result are both objects, you can pass any type you like in and out.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Dear everyone
I already development application using OCR in C# handwriting recognition inventory ticket ( using A4 size). but sometime number of rows and columns are different with same template. could everyone can help me fix it? it is very impotance with me. I already up load my code in here. please help me.
thank you.
trtreterte
modified 8-Feb-15 4:37am.
|
|
|
|
|
rosy84 wrote: it is very impotance with me. so i can not upload here. You're asking for free consultancy here, complete with confidentiality.
I don't think that it will attract a lot of usefull replies.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I know that but in here I cannot upload inventory images and any think like that. i kow in here is free.
thank you for your comment.
trtreterte
|
|
|
|
|
rosy84 wrote: i kow in here is free. Posting is free, and asking questions is. So, if you have a specific question, we can help.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thank Eddy Vluggen
firstly i have inventory ticket (all inventory tickets are same format), I also calculated Vertical Histogram and Horizoltal Histogram to detect rows and columns.
But sometime row is 20 sometime is 21 and sometime got other values. (images already deskew before process)
Could everyone help me fix it?
image link here[^]
My code in here
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Threading;
namespace InventoryOCR
{
struct Column
{
public int first;
public int last;
}
struct Row
{
public int first;
public int last;
public List<Column> columns;
}
class AuditInvoice
{
public ProgressBar progressBar;
public int[] horizontalHisto;
public int[] verticalHisto;
private int width, height;
private Bitmap inputImage;
public List<Row> rows = new List<Row>();
private int top, left, bottom, right;
public int removerows = 0 ;
public void LoadImage(Bitmap bmp)
{
if (bmp != null)
{
inputImage = bmp;
width = inputImage.Width;
height = inputImage.Height;
horizontalHisto = new int[height];
verticalHisto = new int[width];
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride01 = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
toBlackWhite(Scan0, stride01, width, height,180);
bmp.UnlockBits(bmData);
}
}
int Max(int[] histo, int length)
{
int max = 0;
for (int i = 0; i < length; i++)
{
if (max < histo[i])
max = histo[i];
}
return max;
}
public void CalcVerticalHisto(int y1, int y2)
{
BitmapData bmData = inputImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
int stride = bmData.Stride;
unsafe
{
byte* scan0 = (byte*)bmData.Scan0.ToPointer();
for (int x = 0; x < width; x++)
{
verticalHisto[x] = 0;
for (int y = y1; y <= y2; y++)
{
if (scan0[y * stride + x] == 0 || scan0[(y +1)* stride + x] == 0 || scan0[(y+2) * stride + x] == 0 || scan0[(y+3) * stride + x]==0)
verticalHisto[x]++;
}
}
}
inputImage.UnlockBits(bmData);
}
public void CalcVerticalHisto01(int y1, int y2)
{
BitmapData bmData = inputImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
int stride = bmData.Stride;
unsafe
{
byte* scan0 = (byte*)bmData.Scan0.ToPointer();
for (int x = 0; x < width; x++)
{
verticalHisto[x] = 0;
for (int y = y1; y <= y2; y++)
{
if (scan0[y * stride + x] == 0 )
verticalHisto[x]++;
}
}
}
inputImage.UnlockBits(bmData);
}
public void CalcHorizontalHisto()
{
BitmapData bmData = inputImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr p = bmData.Scan0;
unsafe
{
byte* scan0 = (byte*)p;
for (int y = 0; y < height; y++)
{
horizontalHisto[y] = 0;
for (int x = 0; x < stride; x+=3)
{
if (scan0[y*stride+x]==0&&scan0[y*stride+x+1]==0&&scan0[y*stride+x+2]==0)
{
horizontalHisto[y]=horizontalHisto[y]+1 ;
}
}
}
}
progressBar.PerformStep();
inputImage.UnlockBits(bmData);
}
void CalcRows()
{
Row row = new Row();
float maxPixel = Max(horizontalHisto, height);
bool inRow = false;
int y = 0;
int threshold = (int)(maxPixel / 2);
inRow = false;
int i = 1; int j;
for (j = 0; j < height - 1; j++ )
{
if (!inRow && horizontalHisto[j] > (maxPixel - threshold) && horizontalHisto[j + 1] < (maxPixel - threshold))
{
inRow = true;
row.first = j;
continue;
}
if (inRow && horizontalHisto[j] < (maxPixel - threshold) && horizontalHisto[j + 1] > (maxPixel - threshold))
{
inRow = false;
row.last = j+2;
j--;
while (horizontalHisto[++y] > threshold) ;
row.columns = CalcColumns(row.first, row.last, i++);
rows.Add(row);
}
}
progressBar.PerformStep();
}
void RemoveVoidColumns()
{
int numberOfRows = 20, qty = 6, qtyCols = 36;
int i, j, k;
if (rows.Count > numberOfRows)
{
while (rows.Count != numberOfRows)
rows.RemoveAt(rows.Count - 1);
}
for (i = qty; i < numberOfRows; i++)
{
if (rows[i].columns.Count <= qtyCols)
{
rows.RemoveAt(i--);
numberOfRows--;
continue;
}
j = 36;
rows[i].columns.RemoveAt(j--);
}
int dem=0;
for (i = qty; i < rows.Count; i++)
{
CalcVerticalHisto(rows[i].first + 4, rows[i].last - 4);
for (j = 0; j < rows[i].columns.Count; j++)
{
k = rows[i].columns[j].first + 1;
while (k < rows[i].columns[j].last)
if (verticalHisto[k++] > 0)
break;
if (k == rows[i].columns[j].last)
dem++;
}
if (dem >=25)
{
rows.RemoveAt(i--);
removerows++;
}
dem = 0;
}
progressBar.PerformStep();
}
List<Column> CalcColumns(int r1, int r2, int index)
{
CalcVerticalHisto(r1, r2);
int maxPixel = Max(verticalHisto, width);
int threshold = maxPixel - 5;
List<Column> columns = new List<Column>();
Column column = new Column();
bool inCol = false;
for (int x = 1; x < width - 1; x++)
{
if (!inCol && verticalHisto[x] > threshold
&& verticalHisto[x + 1] <= threshold)
{
column.first = ++x;
inCol = true;
}
if (inCol && verticalHisto[x] <= threshold
&& verticalHisto[x + 1] > threshold)
{
switch (index)
{
case 1:
case 2:
column.last = x;
while (verticalHisto[++x] > threshold) ;
break;
default:
column.last = x;
break;
}
inCol = false;
columns.Add(column);
}
}
return columns;
}
List<Column> CalcNoAreaCols(int r1, int r2)
{
CalcVerticalHisto(r1, r2);
bool inCol = false;
List<Column> columns = new List<Column>();
Column column = new Column();
int halfWidth = width / 2;
for (int i = width - 1; i > halfWidth; i--)
{
if (!inCol && verticalHisto[i] == 0 && verticalHisto[i - 1] > 0)
{
column.last = i;
inCol = true;
}
if (inCol && verticalHisto[i] > 0 && verticalHisto[i - 1] == 0)
{
inCol = false;
column.first = i - 1;
columns.Add(column);
}
}
columns.Reverse();
return columns;
}
}
}
thank you.
Rosy
|
|
|
|
|
Dear everyone, please help me.
trtreterte
|
|
|
|
|
I have two applications, a windows application and a windows service. They both need to access the same DLL periodically, however, they cannot access this DLL at the same time.
How can I let one application know to wait till the other is done using the DLL and vise versa?
Thanks in advanced,
JB
|
|
|
|
|
What does that mean, they can't use the DLL at the same time? Is it written in some unmanaged code?
There may be a class in there that can only be used by a single consumer at a time, but then you could still reference and load the DLL from two applications.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
The DLL is a third party component, there is licensing in it to prevent multiple, simultaneous access.
|
|
|
|
|
Aaah, so you want us to help bypass a license?
How would you react if you saw a similar question here asking the remove the license from a product that you created?
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Why can't they access the DLL at the same time?
|
|
|
|
|
The DLL is a third party component, there is licensing in it to prevent multiple, simultaneous access.
|
|
|
|
|
What happens if your applications would access it simultaneously? If it "just" throws an exception and doesn't lock your license or something equally evil, you could implement a simple retry-logic.
Otherwise you could implement a wrapper-DLL that does the synchronizing via a mutex (or semaphore, if it could happen in the future that you upgrade that license to allow X simultaneous accesses).
Mutex class[^]
|
|
|
|
|
You could use a mutex to synchronize access to the DLL.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
do you have an example, or article you can link?
|
|
|
|
|
|
Make a new application (server) that references the 3rd-party dll.
Remove the references to the 3rd-party dll from the other programs(Windows app and service).
Determine how you want the other programs to access the new app (and 3rd-party dll): file directory watcher; message queue; pipes; sockets; remote automation; etc.
Send 3rd-party dll requests from the 2 programs to the new unattended app that handles requests by monitoring a file directory; or message queue; or ...
Results are returned along the same lines.
|
|
|
|
|