I am working with Kanda usb programmer to load data into device microprocessor under WPF framework in c# language. Because the time on loading into microprocessor is long, so I use a background worker to do it.
the way I am using in my source code like as below:
1,Create a background worker after the software ran.
2,Call doWork event of this background worker to load data into microprocessor after the Start button in the UI is clicked.
3,Once doWork event is finished, workCompleted event is called. (there are no codes in the workCompleted method. Just notice the operator by using a messageBox.)
4,Call runWorkAsync method to call doWork event again if the Start button is clicked again by the operator.
My question is:
With this background thread, the Kanda programmer can be initialized, and data can be loaded into microprocessor at the first time doWork event is called. If I call the doWork event again by calling RunWorkAsync method after the Start button is clicked, Kanda programmer can not be initialized! By the way, I had tested that the Kanda programmer can be initialized successfully every time as long as at the first time doWork event is called.
Could anyone tell me why? thanks a lot. Does the background thread need to dispose resource(for example, COM port in the PC) before the doWork event is called again? In my opinion, I only use this background thread, does it need to dispose resource? Does the background thread dispose resources before it go back into thread pool?
Hi everyone, thank you greatly. I had been on this trouble for many days.
Regards,
frank
Source code:
001.public partial class UIBase : Window
002.{
003.private BaseTest _BaseTest;
004.private void btnStart_Click(object sender, RoutedEventArgs e)
005. {
006. if (_BaseTest == null)
007. {
008. _BaseTest = New BaseTest();
009. }
010. btnStart.IsEnabled = false;
011.
012. _BaseTest.RunProcess();
013.
014. }
015.}
016.
017.
018.
019.///
020.
021. /// Logic on background worker.
022.
023. ///
024.
025.class BaseTest
026.{
027.protected BackgroundWorker backgroundworker;
028.
029.public BaseTest()
030.{
031.backgroundworker = new BackgroundWorker();
032.
033. backgroundworker.DoWork += new DoWorkEventHandler(doWork);
034.
035. backgroundworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(WorkerCompleted);
036.
037. backgroundworker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
038.
039. backgroundworker.WorkerReportsProgress = true;
040.
041. backgroundworker.WorkerSupportsCancellation = true;
042.
043.}
044.
045.
046.
047.public void RunProcess()
048. {
049. if (backgroundworker.IsBusy != true)
050. {
051. backgroundworker.RunWorkerAsync();
052. }
053. }
054.
055.
056.public void doWork(object sender, DoWorkEventArgs e)
057. {
058. try
059. {
060. foreach (Board b in UI.UIBase.Boards)
061. {
062. if (!backgroundworker.CancellationPending)
063. {
064. #region Program this board
065.
066. if (InitializeKandaProgrammer(b) == false)
067. {
068. KandaUSB.PSI_RunDevice();
069.
070. continue;
071.
072. }
073.
074. if (KandaUSB.PSI_PROG_Open() == 0)
075. {
076. //Erase
077.
078. KandaUSB.PSI_EraseDevice();
079.
080. //Programm and verify
081.
082. ProgramAndVerify(b);
083.
084.
085. //1,put the device into Run mode, so code will execute.
086.
087. //2,close Kanda programmer.
088.
089. KandaUSB.PSI_RunDevice();
090.
091.
092. KandaUSB.PSI_PROG_Close();
093.
094. }
095. else
096. {
097.
098. KandaUSB.PSI_RunDevice();
099.
100. KandaUSB.PSI_PROG_Close();
101.
102. }
103.
104. #endregion
105.
106. }
107. else if (backgroundworker.CancellationPending)
108. {
109. e.Cancel = true;
110.
111. break;
112.
113. }
114. }
115. }
116. catch (Exception ex)
117. {
118. MessageBox.Show(ex.Message);
119. }
120. }
121.
122.
123.
124.///
125.
126. /// Set the programming speed of the target device and initialize Kanda programmer.
127. ///
128. public bool InitializeKandaProgrammer(Board b)
129. {
130. _ResultInitialize = KandaUSB.PSI_InitProgrammer(b.ProgrammerID, b.DeviceType,
KandaUSB.PSIM_USB);
131.
132. if (_ResultInitialize != 0)
133. {
134. return false;
135. }
136.
137. int _ResultSpeed = KandaUSB.PSI_PROG_Speed(ERS_PROGSPEED);
138.
139. if (_ResultSpeed != 0)
140. {
141. return false ;
142. }
143. return true;
144. }
145.
146.
147.///
148.
149. /// 1,Programme device with Flash mode and verify file loaded after loading is
finished.
150.
151. ///
152.
153. /// The board need to be program.
154.
155. public void ProgramAndVerify(Board _b)
156. {
157. //region Program device
158.
159. KandaUSB.PSI_ProgramFlash(_b.InputFile);
160.
161.
162. //region Verify device
163.
164. KandaUSB.PSI_VerifyFlash(_b.InputFile);
165. }
166.
167.public void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
168. {
169. if(e.Cancelled==true)
170. {
171. MessageBox.Show("Cancelled.");
172.
173. }
174.
175. if (e.Error != null)
176. {
177. MessageBox.Show(e.Error.ToString());
178. }
179. }
180.
181.}
182.
183.
184.
185.
186.
187.
188.
189.///
190.
191. /// We wrapped all the methods contained in ISPPSI.DLL for Kanda programmer.
192.
193. ///
194.
195. class KandaUSB
196. {
197.
198. //Programmer mode constants
199.
200. public static byte PSIM_COM = 1;
201.
202. public static byte PSIM_LPT = 2;
203.
204. public static byte PSIM_USB = 3;
205.
206. public static byte PSIM_JTAG = 4;
207.
208. public static byte PSIM_ISP = 5;
209.
210.
211.
212. //Buffer mode constants
213.
214. public static byte PSIB_FLASH = 1;
215.
216. public static byte PSIB_EEPROM = 2;
217.
218.
219.
220. //Filetype constants
221.
222. public static byte PSI_INTEL = 1;
223.
224. public static byte PSI_MOTOROLA = 4;
225.
226. public static byte PSI_EXTTEK = 5;
227.
228. public static byte PSI_TEK = 6;
229.
230. public static byte PSI_ATMg = 9;
231.
232. public static byte PSI_BIN = 11;
233.
234.
235.
236. //Flash/EEPROM time constants
237.
238. public static byte DEFAULT = 0;
239.
240.
241.
242.
243.
244. //Programming speed constants
245.
246. public static byte SP_FASTEST = 0;
247.
248. public static byte SP_FAST = 1;
249.
250. public static byte SP_MEDIUMF = 2;
251.
252. public static byte SP_MEDIUM = 3;
253.
254. public static byte SP_MEDIUMS = 4;
255.
256. public static byte SP_SLOW = 5;
257.
258. public static byte SP_VERYSLOW = 6;
259.
260. public static byte SP_SLOWEST = 7;
261.
262.
263.
264. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
265.
266. public static extern Int32 PSI_InitProgrammer(string PortName, string DeviceName, byte
Mode);
267.
268.
269.
270. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
271.
272. public static extern Int32 PSI_TestComms();
273.
274.
275.
276. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
277.
278. public static extern Int32 PSI_PROG_Speed(byte bt);
279.
280.
281.
282. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
283.
284. public static extern Int32 PSI_PROG_Open();
285.
286.
287.
288. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
289.
290. public static extern Int32 PSI_PROG_Close();
291.
292.
293.
294.
295.
296. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
297.
298. public static extern string PSI_GetLastError();
299.
300.
301.
302.
303.
304. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
305.
306. public static extern Int32 PSI_EraseDevice();
307.
308.
309.
310.
311.
312. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
313.
314. public static extern Int32 PSI_ProgramFlash(string Filename);
315.
316.
317.
318. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
319.
320. public static extern Int32 PSI_VerifyFlash(string Filename);
321.
322.
323.
324.
325.
326. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
327.
328. public static extern Int32 PSI_ReadFuses(out byte Fuses);
329.
330.
331.
332. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
333.
334. public static extern Int32 PSI_ReadExtFuses(out byte Fuses);
335.
336.
337.
338. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
339.
340. public static extern Int32 PSI_ReadHighFuses(out byte Fuses);
341.
342.
343.
344. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
345.
346. public static extern Int32 PSI_ProgramFuses(byte Fuses);
347.
348.
349.
350. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
351.
352. public static extern Int32 PSI_ProgramExtFuses(byte Fuses);
353.
354.
355.
356. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
357.
358. public static extern Int32 PSI_ProgramHighFuses(byte Fuses);
359.
360.
361.
362. [System.Runtime.InteropServices.DllImport("ISPPSI.DLL")]
363.
364. public static extern Int32 PSI_RunDevice();
365.
366. }
Sam HobbsPosted Aug 19, 2011, 1:11 PM
frank zhangPosted Aug 19, 2011, 6:50 AM
1,The action that power off and power on back the device doesn't change anything.
2,I don't find a un-initialize method from Programmer Manual which Kanda supports.
3,The snippet of codes what you said is not executed. close method would be used only after open method is called.
Thanks.
Sam HobbsPosted Aug 19, 2011, 12:45 AM
I see that your program is calling PSI_InitProgrammer but I don't see a corresponding un-initialize. Are you sure there is not an un-initialize?
I notice that when InitializeKandaProgrammer(b) is called and returns false then KandaUSB.PSI_RunDevice() is called but KandaUSB.PSI_PROG_Close() is not called. Are you sure that is correct? It looks suspicious to me.
frank zhangPosted Aug 18, 2011, 9:22 PM
I initialized an background worker instance and want to use this instance to execute doWork event many times.
At the first time the doWork event is executed, my Kanda programmer can work well, but my Kanda programmer cannot work when this doWork event is called again. The error message is "No COM/LPT ports or no AVR USB Programmers Found" when KandaUSB.PSI_InitProgrammer(b.ProgrammerID, b.DeviceType, KandaUSB.PSIM_USB) is executed.
The PSI_InitProgrammer method is supported by Kanda, there are no more detailed info about this method. I don't know how it works.
Regards,
frank
Sam HobbsPosted Aug 18, 2011, 6:14 PM
VulpesPosted Aug 18, 2011, 10:29 AM
frank zhangPosted Aug 18, 2011, 7:36 AM
Thank you for so detailed answer.
I have been debugging this problem today, and I found that Kanda programmer can be initialized again if the background thread ID is same as the value of background thread ID the doWork event is called at the first time! I checked the background thread ID by using Thread.CurrentThread.ManagedThreadId in doWork method and find this thing.
Does this mean that this thread didn't dispose resources it managed and other thread cann't to use?
Now, I get knowed that a free thread in thread pool would be used randomly to execute doWork event. Is there a way that I can specify which thread in the thread pool to use rather than a random thread?
Regards,
frank
VulpesPosted Aug 18, 2011, 7:02 AM