tag:blogger.com,1999:blog-55120752330138397532024-03-05T17:07:59.879-08:00sunshakingsunshaking's blog. computer graphics.Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.comBlogger41125tag:blogger.com,1999:blog-5512075233013839753.post-39408384642584322382017-04-28T23:49:00.002-07:002017-04-29T03:41:45.348-07:00Detected EEG wave that can tell whether eyes are open or closedThis humble equipment which hides in the paper box can detect and record EEG wave now. By filtering and Fourier transformed to the frequency domain, we can tell whether the testee's eyes are open or closed. The middle part of the graph, which has lower signal, is the period of time that eyes were closed.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIPQzEQXz14mqaKwq32zxAvEMKwEEFRgIrNH84Yq0izaGvYatnS4_S1fkulmMbCxVUrEtFnPIRAKVjLoo-7Q09qhDOlS5aQ8vpoVhuZ0nDnbNgyIDDpbZTaGKKodlvTtzAnOE3M4gSeg_k/s1600/DSC_0316.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIPQzEQXz14mqaKwq32zxAvEMKwEEFRgIrNH84Yq0izaGvYatnS4_S1fkulmMbCxVUrEtFnPIRAKVjLoo-7Q09qhDOlS5aQ8vpoVhuZ0nDnbNgyIDDpbZTaGKKodlvTtzAnOE3M4gSeg_k/s200/DSC_0316.JPG" width="200" /></a></div>
<div>
<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXZ26SkPlEGWACK_OWp2X6ifwhrCKfp1iCjOatzgWFn45k2lIIRQHMFACFCKKMDdZONind1t5DKTh-9TjKzs7B24zDECc5OTvj9gAk2N6v_3UMHX5v5HkVBTPyTo2FLEFXyEYAz1J2HZmn/s1600/EEG_EYE01.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXZ26SkPlEGWACK_OWp2X6ifwhrCKfp1iCjOatzgWFn45k2lIIRQHMFACFCKKMDdZONind1t5DKTh-9TjKzs7B24zDECc5OTvj9gAk2N6v_3UMHX5v5HkVBTPyTo2FLEFXyEYAz1J2HZmn/s320/EEG_EYE01.JPG" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikkFXHUTv3uehyCaB8Aac51pFhZf6-AOrgQ3nh8MIpWajSswu2zb9f1sYaSDR49NlVAAUMdZq_kTEpJ6Ai59lktSTeueGnujVhLn5sR46LV0LKUW_caDiEML50vu1Tfv_ZevYvfEU0vxZ_/s1600/EEG_EYE02.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikkFXHUTv3uehyCaB8Aac51pFhZf6-AOrgQ3nh8MIpWajSswu2zb9f1sYaSDR49NlVAAUMdZq_kTEpJ6Ai59lktSTeueGnujVhLn5sR46LV0LKUW_caDiEML50vu1Tfv_ZevYvfEU0vxZ_/s320/EEG_EYE02.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
When eyes closed, the amplitude of the signal decreased significantly. It has a great difference with the signal that generated when eyes are open.</div>
</div>
<div>
<br /></div>
<div>
And when eyes are open, the beta wave which mainly distributes around 20Hz appears, together with some other higher components.</div>
<div>
<br /></div>
<div>
In the beginning, I was guessing the widely distributed signals are noise, they look like white noise or 1/f noise. After deep investigation, I confirmed that it's EEG signal, and mainly is the beta wave.</div>
<div>
<br /></div>
<div>
And happily, I got to know a guy that is currently pursuing his master's degree in a university in Canada, he is studying the method of detect epilepsy evidence in EEG wave. He is using wavelet to extract some specific wave from the signal. He would be a great help to my project.</div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com7tag:blogger.com,1999:blog-5512075233013839753.post-67736918580226499072017-04-25T04:06:00.000-07:002017-04-25T04:06:09.329-07:00My first ECG signal recordingFor the first time, I made it, I recorded the ECG signal, by this messy, tiny circuit.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFG3-JnqDy3_oUD_tuhBUiTqVYClJ5rqY1uw73EsSfOepGvPrbyWaKG9Vzq0EZE17JwuhACn0glxgX-6YHc2FtA7BtFMSyUvvo-6jS5OJ1RzT0TA_OwVuaj1ggnlWqdmSQ85PK9_VdWzcs/s1600/SignalECG.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFG3-JnqDy3_oUD_tuhBUiTqVYClJ5rqY1uw73EsSfOepGvPrbyWaKG9Vzq0EZE17JwuhACn0glxgX-6YHc2FtA7BtFMSyUvvo-6jS5OJ1RzT0TA_OwVuaj1ggnlWqdmSQ85PK9_VdWzcs/s320/SignalECG.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
Figure: The ECG signal</div>
<span id="goog_1306194607"></span><span id="goog_1306194608"></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWl3FxaoQ6_pDRaCz1kbB-97KEUMyPBdkfViD1bhu02DPrPjZ7XYlrzqHOyFn4kYq2O56zl3QFg9HtIv17_YOFHIYZICgA0ayGgOklkXP1Td2p7gjR01tWzBxcwE-XpUNCWLpLj1QmapgB/s1600/hardware.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWl3FxaoQ6_pDRaCz1kbB-97KEUMyPBdkfViD1bhu02DPrPjZ7XYlrzqHOyFn4kYq2O56zl3QFg9HtIv17_YOFHIYZICgA0ayGgOklkXP1Td2p7gjR01tWzBxcwE-XpUNCWLpLj1QmapgB/s320/hardware.jpg" width="180" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
The circuit was designed by my partner</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
Here is the system structure:<br />
<br />
human body -> electrodes -> leads -> ADS1298 -> serial port -> PC -> C# app -> matlab<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com1tag:blogger.com,1999:blog-5512075233013839753.post-22077001594644554572016-11-04T18:48:00.002-07:002016-11-04T18:48:45.988-07:00How to let SharpGL capturing KeyDown event?Issue:<br />
<br />
<ul>
<li>SharpGL won't capture KeyDown event</li>
</ul>
<div>
Solution:</div>
<div>
<ul>
<li>Make OpenGLControl focusable, like this: Focusable="True"</li>
<li>Set focus on the OpenGL control in the hosting window: OpenGLControl.Focus();</li>
</ul>
<div>
If the OpenGL control is in a User Control, then set focus on the user control in the hosting window of the user control.</div>
</div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-77391535593901948742016-09-29T01:57:00.000-07:002016-09-29T01:57:04.504-07:00Solution for: (Visual Studio 2015)Error while trying to run project: Unable to start debuggingI googled around. Many other solutions didn't work, except this one.<br />
<br />
Issue: When you trying to debug the application, VS says "Error while trying to run project: Unable to start debugging".<br />
Solution: Delete your .suo file of your solution.<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-62892680626760299802016-06-26T07:13:00.003-07:002016-06-26T07:18:16.888-07:00Convert MIT-BIH Polysomnographic data to mat (Matlab) format.mat file could be loaded directly into Matlab. But MIT-BIH Polysomnographic data is not a .mat format. although, https://www.physionet.org/cgi-bin/atm/ATM offers a converter that could convert to .mat format, but be careful, it only gives you first 1000000 points, but not all data. So how to convert the whole data file to .mat? Fortunately, the convertion tool "wfdb2mat" is also offered by www.physionet.org. Just go https://www.physionet.org/physiotools/, click "Software Index" https://www.physionet.org/physiotools/software-index.shtml. And find WFDB links<br />
https://www.physionet.org/physiotools/wfdb.shtml, click it. Find "Ready-to-run, precompiled binaries" https://www.physionet.org/physiotools/binaries/. OK, in this page you will find the tool in binary format. I use windows, so I downloaded the windows version.<br />
<br />
Here is a command line example:<br />
<br />
bin\wfdb2mat -r slpdb/slp14 -f 0 -t 21600 -s 2 >slp14m.info<br />
<br />
Make sure you have .hea file along with .dat file. The last command will produce slp14m.mat and other stuffs. slp14m.mat is just you want. Try to load it into matlab:<br />
<br />
eegdata = load('slp14m.mat');<br />
<br />
All are done!<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-41304240069085214262016-05-17T01:15:00.001-07:002016-05-17T01:15:18.812-07:00Digital Elliptic Filter in Matlab(Just learning how to use elliptic filter in Matlab)<br />
<br />
The elliptic filter works pretty well, so efficient. The following filter will band 50Hz and near frequencies (see the third figure). And the last figure shows the filtered signal.<br />
<br />
==== m code started ====<br />
<br />
<pre>clear
Rp = 5; % peak-to-peak passband ripple, the smaller the smoother
Rs = 60; % stopband attenuation
Fs = 250; % sample rate
Wp = [47, 53]/Fs*2; % passband edge frequency
Ws = [48, 52]/Fs*2; % stopband edge frequency
[N, Wn] = ellipord(Wp, Ws, Rp, Rs); % find the minimum order of the required filter
fprintf('Wn %f, %f\n', Wn(1)*Fs/2, Wn(2)*Fs/2);
[b,a] = ellip(N,Rp,Rs, Wn,'stop'); % design an elliptic filter
freqz(b,a); % draw frequency response of the filter
title(['ellipord Analog bandstop filter order N=',num2str(N)]);
xlabel('Frequency(Hz)');
tseq = 0: 1/Fs :6;
dataIn = sin(tseq*10 *2*pi) + sin(tseq*50 *2*pi) + sin(tseq*52 *2*pi) + sin(tseq*48 *2*pi);
dataOut = filter(b,a,dataIn);
figure(2);
plot(dataIn);
figure(3);
plot(dataOut);
</pre>
<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtt_DO9edrkDMJal0X260l1XPRav24e6RXoJ8vLIOGAdTdnjl36GXZGhmz2RGb008qDVg-38zbKMatOnmjXd5eUGMh5x6T3j3nxljcKj6zNQhc2fugwuYcz1jEORYDTmduyD-7l8EAmCJ0/s1600/elliptic_filter_result.JPG" imageanchor="1"><img border="0" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtt_DO9edrkDMJal0X260l1XPRav24e6RXoJ8vLIOGAdTdnjl36GXZGhmz2RGb008qDVg-38zbKMatOnmjXd5eUGMh5x6T3j3nxljcKj6zNQhc2fugwuYcz1jEORYDTmduyD-7l8EAmCJ0/s320/elliptic_filter_result.JPG" width="320" /></a>Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-19500397663744246112016-01-18T01:07:00.000-08:002016-01-18T01:07:20.156-08:00vector::operator [] is time consumingI am handling large amount of data (4000*4000 double). I found vector::operator [] is really expensive in terms of CPU cost.<br />
<br />
vector<double> arr = AllocateArray(4000, 4000);</double><br />
while( _all_elements_in_arr_)<br />
{<br />
arr[i] = x; // it's extremely slow.<br />
}<br />
<br />
So avoid of using operator [], instead, use direct address of the buffer could improve the performance tremendously:<br />
<br />
<b>double * buffer_addr = &arr[0];</b><br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-42054201183628778272015-12-18T22:10:00.001-08:002015-12-18T22:10:13.181-08:00[IDL 2 CPP] Let Bison/Flex Generate C++ ParserAlthough C++ isn't a very modern language, C could make you upset even more. I'm developing a translator which could translate IDL (Interactive Data Language) to C++, and had enough of the ancient C because I need various complex data struct to hold all kind of information that needed when doing the translation. So it's absolutely a good idea that let Bison/Flex to generate a C++ parser. But the way of enabling C++ for Bison/Flex is hard indeed. Bison/Flex lack documents that tells you how to develop a complete C++ parser. When you turn on the C++ option for Bison/Flex, tremendous compiling errors are waiting for you. I read so many articles, and want to say thank you to all these authors. And I will share you the whole cook book of letting Bisong/Flex generating C++ Parser.<br />
<br />
<b>Download Win Flex Bison</b><br />
I tried two windows versions. This is the good one to support C++ parser.<br />
http://sourceforge.net/projects/winflexbison/<br />
<br />
<b>Option for Bison</b><br />
These two options tell Bison to generate a C++ parser. The file lalr1.cc is in the win_flex_bison downloaded package.<br />
<br />
%language "c++"<br />
%skeleton "lalr1.cc"<br />
<br />
<b>Setup Parser's Class Name</b><br />
The following option give a name to the parser class.<br />
<br />
%define parser_class_name "idl_parser"<br />
<br />
The parser class would look like as following<br />
<br />
/// A Bison parser.<br />
class idl_parser<br />
{<br />
<div>
<br /></div>
<div>
<b>Pass Essential Arguments to the Parser</b></div>
<div>
<div>
You have to pass scanner which would provide yylex, to the parser. The parser could call yylex and obtain a token each time. "translator" could hold some important data, but depends on your needs. "arg_yyin" is the input source code file.</div>
<div>
<br /></div>
<div>
%parse-param {yy::IdlTranslator& translator}</div>
<div>
%parse-param {yy::IdlScanner& scanner}</div>
<div>
%parse-param {std::ifstream* arg_yyin}</div>
<div>
%parse-param {std::ofstream* outputStream}</div>
</div>
<div>
<br /></div>
The parser ctor looks like as following.<br />
<br />
idl_parser (yy::IdlTranslator& translator_yyarg, yy::IdlScanner& scanner_yyarg, std::ifstream* arg_yyin_yyarg, std::ofstream* outputStream_yyarg);<br />
<br />
All arguments passed in, the parser will store them in member variables.<br />
<br />
/* User arguments. */<br />
yy::IdlTranslator& translator;<br />
yy::IdlScanner& scanner;<br />
std::ifstream* arg_yyin;<br />
std::ofstream* outputStream;<br />
<br />
<b>Tell the Parser the Prototype of the yylex</b><br />
"yylval" is used to return token string from scanner to parser. "yylloc" is an argument which could tell the current location in the source file. This parameter is enabled by %locations . If you didn't use %locations, then there would be no yylloc.<br />
<br />
The following macro definition usually be defined in scanner header file. And included by bison .y file and flex .l file.<br />
<br />
#ifndef YY_DECL<br />
# define YY_DECL \<br />
yy::idl_parser::token_type \<br />
yy::IdlScanner::lex(yy::idl_parser::semantic_type* yylval, yy::idl_parser::location_type *yylloc)<br />
<div>
<br /></div>
And in your grammar file (.y) define yylex macro.<br />
<br />
#define yylex<span class="Apple-tab-span" style="white-space: pre;"> </span>scanner.lex<br />
<br />
The parser will call lex as following<br />
<br />
YYCDEBUG << "Reading a token: ";<br />
yychar = yylex (&yylval, &yylloc);<br />
<br />
By defining the yylex macro, parser actually calls scanner.lex().<br />
<br />
<b>Implementing the Scanner</b><br />
Pay attention to the first part of the following code please. <span style="background-color: yellow;">It redefines yyFlexLexer, so the class yyFlexLexer in file "FlexLexer.h" becomes IdlFlexLexer. It very important, it avoids many conflicts.</span> But it's really a poor technique.<br />
<br />
The following is part of the scanner's header file.<br />
<br />
#ifndef __FLEX_LEXER_H<br />
#define yyFlexLexer IdlFlexLexer<br />
#include "FlexLexer.h"<br />
#undef yyFlexLexer<br />
#endif<br />
<br />
#include "idl.tab.hh"<br />
<br />
<br />
namespace yy<br />
{<br />
class IdlScanner : public IdlFlexLexer<br />
{<br />
public:<br />
IdlScanner(std::ifstream* arg_yyin);<br />
<br />
virtual ~IdlScanner();<br />
<br />
virtual idl_parser::token_type lex(<br />
idl_parser::semantic_type* yylval,<br />
yy::idl_parser::location_type *yylloc<br />
);<br />
};<br />
}<br />
<br />
<b>Have a Look at the Implementation of IdlScanner::lex()</b><br />
The file lex.???.cc is the lexer implementation file. The file is generated by flex. In this file, the macro YY_DECL just defined before, is used here for the implementation code.<br />
<br />
YY_DECL<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>register yy_state_type yy_current_state;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>register char *yy_cp, *yy_bp;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>register int yy_act;<br />
...<br />
<br />
<b>How does the Input File Passed into Scanner</b><br />
The scanner class is derived from class yyFlexLexer which is defined in FlexLexer.h. The input file "std::ifstream* in" is actually passed to the parent class via ctor. Remember yyFlexLexer was defined as IdlFlexLexer.<br />
<br />
IdlScanner::IdlScanner(std::ifstream* in)<br />
: IdlFlexLexer(in)<br />
{<br />
}<br />
<br />
The implementation of yyFlexLexer ctor is in file lex.???.cc, which is generated by flex. The input file arg_yyin is stored in yyin, a member variable of yyFlexLexer. yyin is used to be a global variable in C lexer version. If yyin is NULL, then the lexer would use stdin as input.<br />
<br />
yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout )<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yyin = arg_yyin;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yyout = arg_yyout;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yy_c_buf_p = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yy_init = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yy_start = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yy_flex_debug = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yylineno = 1;<span class="Apple-tab-span" style="white-space: pre;"> </span>// this will only get updated if %option yylineno<br />
<div>
<br /></div>
<b>Invoke the Parser</b><br />
First create the scanner with the input file, and then pass the scanner to the parser. When you call parser.parse(), the parser will call scanner.lex() to get tokens one by one.<br />
<br />
std::ifstream *inputFile = new std::ifstream();<br />
inputFile->open("some source file here");<br />
<br />
std::ofstream *outputFile = new std::ofstream();<br />
outputFile->open("some output file here");<br />
<br />
IdlScanner scanner(inputFile);<br />
<br />
idl_parser parser(*this, scanner, inputFile, outputFile);<br />
<br />
int parse_ret = parser.parse();<br />
<div>
<br /></div>
<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-48163450019736551702015-11-29T21:25:00.001-08:002015-11-30T00:12:23.305-08:00[IDL 2 CPP] Implement Variable DefinitionsSince IDL (Interactive Data Language) is a kind of <a href="https://en.wikipedia.org/wiki/Dynamic_programming_language">dynamic typed language</a> (dynamic language for short), it doesn't have variable declarations. So we have to add declarations in translated C++ source code.<br />
<br />
The basic method of adding declarations is by using mid-rules in Bison grammar file.<br />
<br />
As following, initialize a data structure that could store variable names, and then each time the parse meets an assignment statement, store the variable name for future use. The following code show the way of recording variable names. But its not accurate, because unary_expression doesn't equal to variable name, sometimes it's an element of an array or some other ting. So here we need more complex code logic to accomplish it. But I won't put these code here because here is just a show of high level of structure of the method.<br />
<br />
<span style="color: #cc0000;">assignment_statement:</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>unary_expression '=' expression</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>{printf("bison got assign statement: %s = %s\n", $1, $3);</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>VariableNameSet_TryAdd($1);</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = AllocBuff();</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "%s = %s;", $1, $3);</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>;</span><br />
<div>
<br /></div>
<div>
And at last, when composing the C++ function, put the variable declarations at the beginning of the function.</div>
<div>
<br /></div>
<span style="color: #cc0000;">function_definition:</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>KEY_FUNCTION identifier parameter_list_line</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>{</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>VariableNameSet_Init();</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>statement_list KEY_END end_of_line</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>{</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>char *buf = AllocBuff();</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>IncreaseTab($5, buf);</span><br />
<span style="color: #cc0000;"><br /></span>
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = AllocBuff();</span><br />
<span class="Apple-tab-span" style="color: #cc0000; white-space: pre;"> </span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>char *var_decl_buf = AllocBuff();</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>VariableNameSet_DecleareVariables(var_decl_buf);</span><br />
<span class="Apple-tab-span" style="color: #cc0000; white-space: pre;"> </span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>char *var_decl_buf_tabbed = AllocBuff();</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>IncreaseTab(var_decl_buf, var_decl_buf_tabbed);</span><br />
<span class="Apple-tab-span" style="color: #cc0000; white-space: pre;"> </span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "Variant %s%s{\n%s%s}%s\n", $2, $3, var_decl_buf_tabbed, buf, $7);</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>printf("IDL function: [%s]\n", $$);</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="color: #cc0000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>;</span><br />
<br />
<br />
<div>
<br /></div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-58680994375212220782015-11-28T08:18:00.000-08:002015-11-28T16:51:49.862-08:00[IDL 2 CPP] Translate IDL Array Subscript Ranges to C++I started a project that translates huge amount of IDL codes to C++ for sake of performance improvements. IDL is acronym for Interactive Data Language. This is <a href="http://www.exelisvis.com/ProductsServices/IDL.aspx">IDL's homepage</a>. And here is <a href="https://en.wikipedia.org/wiki/IDL_(programming_language)">Wikipedia page</a>.<br />
<br />
Since the original data processing program which was written in IDL is so large, it's impossible to translate manually, I decide to develop a translator then translate it into C++ source code. I've worked on it for a couple of weeks. And today I finished the ranged array part. I think it's interesting so I'm going to share the development experience for you.<br />
<br />
I am using flex/bison to generate a parser. The grammar rules for IDL's array and subscripts are here(ask me for sample code):<br />
<br />
<span style="color: purple;">postfix_expression:</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>primary_expression</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>| postfix_expression '[' array_subscripts ']'</span><br />
<span style="color: purple;"><br /></span>
<span style="color: purple;">array_subscripts:</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>array_subscript</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>| array_subscripts ',' array_subscript</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>;</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: purple;"> </span></span><br />
<span style="color: purple;">array_subscript:</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>expression</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>| range_or_whole_range ':' range_or_whole_range</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>;</span><br />
<span style="color: purple;"><br /></span>
<span style="color: purple;">range_or_whole_range:</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>expression</span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>| '*'<span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="color: purple;"><span class="Apple-tab-span" style="white-space: pre;"> </span>;</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
No action codes here yet. These grammar rules cover simple array subscripts which will visit an element of an array, and also the subscript ranges case. For the simple case, the IDL code is easy to translate. For example, IDL code:<br />
<br />
a = b[1]<br />
<br />
which would be translated to<br />
<br />
a = b[1];<br />
<br />
Just exactly the same code in C++. But it would be more complex if the code uses ranged array, like this:<br />
<br />
a = b[1:10]<br />
<br />
Since there is no relevant grammar in C++, we have to do some fundamental support in C++. Firstly, there should be an object which could represent a range of an array. Say, we have this:<br />
<br />
class ArrayDimDesc<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>int size;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>int startIndex;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>int endIndex;<br />
};<br />
<br />
class RangedArray<br />
{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>void* array;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>int Dimensions;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>ArrayDimDesc arrayDimDesc[8];<br />
};<br />
<br />
So IDL ranged array b[1:10] could be represented by class RangedArray object. This way made things easier. Replace b[1:10] by a function call to MakeArrayRange1D(), the whole statement can be translated just as simple array subscript case.<br />
<br />
Let me show you a more complex IDL code:<br />
<br />
coeffbk = where(sset.bkmask[nord:*, 1, 2:3] NE 0)<br />
<br />
And the translated C++ code is:<br />
<br />
coeffbk = where(MakeArrayRange3D(sset.bkmask, nord, -2, 1, -1, 2, 3) != 0);<br />
<br />
I haven't finished all the work. But the main idea is just as above. There are lots of further work to do:<br />
1, Memory management<br />
2, Introduce smart pointer?<br />
3, Is it necessary to move MakeArrayRange3D in front of the statement?<br />
<br />
<br />
<br />
==== BISON grammar rules for IDL ranged array ======================<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
postfix_expression:<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>primary_expression<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| postfix_expression '[' array_subscripts ']'<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = AllocBuff();<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// check if array_subscripts is a range<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if(IsRangedSubscripts($3))<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>FillMinusOneToEmptyRange($3);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// case 1: range, compose a ranged array; $3 is subscripts<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// MakeArrayRange(array, startIndex, endIndex)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>if($3->dimension == 1)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// 1 dim<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "MakeArrayRange1D(%s, %s, %s)",<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$1,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeEnd);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>else if($3->dimension == 2)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "MakeArrayRange2D(%s, %s, %s, %s, %s)",<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$1,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeEnd,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[1].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[1].rangeEnd);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>else if($3->dimension == 3)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "MakeArrayRange3D(%s, %s, %s, %s, %s, %s, %s)",<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$1,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[0].rangeEnd,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[1].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[1].rangeEnd,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[2].rangeStart,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$3->subscriptsRange[2].rangeEnd);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>else<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// unsupport dimension<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>yyerror("Unsupported array dimension in ranged array, dimension is %d.\n", $3->dimension);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>YYABORT;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>else<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// case 2: scalar, simple and easy case<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>char *subscript_buf = AllocBuff();<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>subscript_buf[0] = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>int pos = 0;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>for(int i=0; i<$3->dimension; i++)<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s((subscript_buf+pos), TEXT_BUFFER_LEN, "[%s]", $3->subscriptsRange[i].rangeStart);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>pos = strlen(subscript_buf);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// ##ATTENTION :IDL array subscripts are different than those of C++'s##<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "%s%s",<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$1,<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>subscript_buf);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// release subscript_buf<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>printf("array final code: %s\n", $$);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| postfix_expression '.' IDENTIFIER<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = AllocBuff();<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>sprintf_s($$, TEXT_BUFFER_LEN, "%s.%s", $1, $3);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| function_call<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
array_subscripts:<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>array_subscript<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = Malloc(sizeof(struct ArraySubscripts));<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$->dimension = 1;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy($$->subscriptsRange[0].rangeStart, $1->rangeStart);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy($$->subscriptsRange[0].rangeEnd, $1->rangeEnd);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>// release $1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| array_subscripts ',' array_subscript<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy($$->subscriptsRange[$$->dimension].rangeStart, $3->rangeStart);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy($$->subscriptsRange[$$->dimension].rangeEnd, $3->rangeEnd);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$->dimension++;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
array_subscript:<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>expression<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{// single subscript<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>struct ArraySubscript *pArraySubscript = Malloc(sizeof(struct ArraySubscript));<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy(pArraySubscript->rangeStart, $1);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>pArraySubscript->rangeEnd[0] = NULL;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = pArraySubscript;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| range_or_whole_range ':' range_or_whole_range<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>{// Ranged subscript<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>struct ArraySubscript *pArraySubscript = Malloc(sizeof(struct ArraySubscript));<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy(pArraySubscript->rangeStart, $1);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strcpy(pArraySubscript->rangeEnd, $3);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>$$ = pArraySubscript;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>;<br />
<br />
range_or_whole_range:<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>expression<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>| '*'<span class="Apple-tab-span" style="white-space: pre;"> </span>{ $$ = "*"; }<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-71014565306451137312015-03-11T06:20:00.003-07:002015-03-11T06:20:20.670-07:00Optimizing by ANSYS - Objective Function Defined by Other SoftwareKey Points:<br />
<br />
<ol>
<li>You have an objective function to be optimized (to find a minimum/maximum point)</li>
<li>But the function is defined by a software other than ANSYS</li>
<li>The function doesn't have a mathematical formula</li>
</ol>
<br />
<br />
Suppose you have an objective function which is defined by a complex software, say an FEM or CFD software. The function has one or several variables, and the function generates different values regarding different variable values input.<br />
<br />
Basic idea of the solution is by using /sys command in ANSYS APDL code which let ANSYS to invoke your software, and evaluate the function. ANSYS will invoke your software repeatedly until it finds a minimum/maximum point.<br />
<br />
Key points for data transfering from ANSYS to your software and vice versa:<br />
1, Your software that defining the objective function should parameterizing the model (the function), so that it can accept one or more parameters and generates the function value.<br />
2, Your software should have a way of passing value to parameter(s), such as command line or an input file.<br />
3, Your software should have a way of passing back the function value, such as program exit code or an output file.<br />
<br />
Here is an example of the solution with the way of passing value that passes data by input/output file.<br />
<br />
TASCA is the software which defines the objective function. "tascain.txt" is the input file, and tascout.txt is the output file.<br />
<br />
vwrite puts the value of X to the input file. Then the code invokes TASCA. TASCA will read the data from "tascain.txt", and evaluate the function, and then writes the function value to "tascaout.txt". The function value will be read from the file and stores in A1 and V.<br />
<br />
FILE: volu.inp<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>*DIM, A1, array, 2,1
X=1.4
*cfopen, tascain,txt
*vwrite, X
(F10.2)
*cfclose
/sys, TASCA evaluate
*vread, A1(1,1), tascaout,txt, c:\working, JIK, 1,1
(F6.2)
V=A1(1,1)
</code></pre>
<br />
The following shows the optimization control file. V defined as the objective function. The makes ANSYS to find the minimum value of the objective function. To start optimization, type these command in the command input box of the ANSYS: <span style="background-color: yellow;">/input, optovlu,inp</span> .<br />
<br />
FILE: optvolu.inp<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>/clear,nostart
/input,volu,inp
/opt
opanl,volu,inp
opvar,X,dv,1.3,1.9,1e-2
opvar,V,obj,,,1e-2
opkeep,on
optype,subp
opsave,optvolu,opt0
opexec
</code></pre>
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com1tag:blogger.com,1999:blog-5512075233013839753.post-527508760160639282015-03-06T05:13:00.001-08:002015-03-06T05:13:07.637-08:00Loading Resources From Assembly and Assign to An Element ProgramaticallySuppose that you have resource in your assembly:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code> <Style x:Key="TextBlock_left" TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</code></pre>
<br />
And then you want to assign this style to an element:<br />
DataGridTextColumn.ElementStyle = (Style)FindResource("TextBlock_right");<br />
<br />
That's it!Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-12497271632583639302015-01-06T20:56:00.003-08:002015-01-06T20:56:44.866-08:00Free Charting Tool For WPF C#"Dynamic Data Display" is an extremely powerful, userful and free charting tool for WPF and C#. If you are looking for a charting tool, and upset with commercial charting tool and library all over the world, then Dynamic Data Display is the best for you.<br />
<br />
http://www.mesta-automation.com/real-time-line-charts-with-wpf-and-dynamic-data-display/Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-60957140306004923632013-12-03T01:34:00.002-08:002013-12-03T04:30:40.325-08:00Simplify Asynchronous Programming with C# "yield return"A few words ahead, please see <a href="http://msdn.microsoft.com/en-us/magazine/cc163323.aspx">http://msdn.microsoft.com/en-us/magazine/cc163323.aspx</a>, for the article by inventor of this technology. My post is just a reinvent of the Jeffrey's idea. But my implementation is easy to understand. I read the code by Jeffrey, it's large and hard to digest.<br />
<br />
(Next article: Nested IEnumerable functions.)<br />
<br />
OK, here we started with my understandable implementation.<br />
<br />
Asynchronous programming is extremely important and useful when you are developing an internet server which is going to support large concurrent requests. When dealing with internet data transmission, blocking mode with one thread handling one request is the one of the most popular traditional technologies. Programmers like it because it's easy to implement. On par with traditional programming technologies, asynchronous programming has many advantages.<br />
<br />
<ol>
<li>Far less threads involved, reduce large amount of memory usage.</li>
<li>Since you don't have to create so many threads, its really responsive to handle an incoming request.</li>
</ol>
<div>
Though it's hard to implement, of course, and it's really easy to introduce bugs. Asynchronous calls always appear in Begin/End functions pair, for example, HttpWebRequest.BeginGetResponse() and HttpWebRequest.EndGetResponse(). You have to call the BeginGetResponse() first, passing in a call back function, so that when it could be called and you got notified when BeginGetResponse() succeeded with a real response object. If your code flow involves several asynchronous calls, then your code is extremely hard to understand and maintain, since your code logic would be teared into several functions.</div>
<br />
So, how to make your code stay in beautiful, logical, human readable form of linear structure, avoiding of tearing it into pieces, but still you could enjoy the high performance asynchronous programming technology? The answer is "yield return".<br />
<br />
The basic idea of yield return is to form a state machine by writing the state changing logic into a single function or nested function calls. The coding style looks like the code of traditional technology of blocking mode data transmission. Every yield return will return from the function with all state reserved, and when last time the function being called, the code will be executed from last yield return statement.<br />
<br />
See this simple example:<br />
<br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"> <span style="color: blue;">private</span> IEnumerable<<span style="color: blue;">int</span>> Foo()
{
<span style="color: green;">// some code here</span>
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 1;
<span style="color: green;">// some code here</span>
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 2;
<span style="color: green;">// some code here</span>
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 0;
<span style="color: green;">// some code here</span>
}</code></pre>
<br />
<br />
Foo() is a function, also it's a state machine. Every time you call it the function will resume execution at the point that last time returned. For sure that every local variable remains in its state of last yield return. OK, let's see how to execute this function:<br />
<br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"> <span style="color: blue;">private</span> <span style="color: blue;">void</span> Driver()
{
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> ele <span style="color: blue;">in</span> Foo())
{
<span style="color: green;">// do something</span>
}
}
</code></pre>
<br />
It's time to show the core of the technology. Let's incorporate the state machine function with asynchronous function calls.<br />
<br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"> <span style="color: blue;">private</span> IEnumerable<<span style="color: blue;">int</span>> Foo()
{
<span style="color: blue;">var</span> ar = HttpWebRequest.BeginGetResponse(callbackHandler);
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 1;
<span style="color: blue;">var</span> response = HttpWebRequest.EndGetResponse();
response.DoSomthing();
}
</code></pre>
<br />
The code isn't real working code, just for theory illustration. The first statement calls BeginGetResponse() passing a callback handler in. The callback handler won't be called until BeginGetResponse() finishing the work. During this period of time, no thread of your app work for these stuffs. So you don't have to pay the price to wait for BeginGetResponse() to return, for example, a thread waiting by semaphore or event. Thus we have a chance to make Foo() to execute the rest of the code. But Driver() can't drive the execution for us. So we have to upgrade our Driver() to a real driver which can drive Foo() through all of its async steps.<br />
<br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> AsyncDriver
{
<span style="color: blue;">public</span> IEnumerator<<span style="color: blue;">int</span>> iterator;
<span style="color: blue;">public</span> <span style="color: blue;">void</span> AsyncCallback(IAsyncResult ar)
{
DriveToNext();
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> DriveToNext()
{
iterator.MoveNext();
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> AsyncCallback(IAsyncResult ar)
{
DriveToNext();
}
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> Main()
{
AsyncDriver asyncDriver = <span style="color: blue;">new</span> AsyncDriver();
asyncDriver.iterator = Foo().GetEnumerator();
}
<span style="color: blue;">private</span> IEnumerable<<span style="color: blue;">int</span>> Foo(AsyncDriver asyncDriver)
{
<span style="color: blue;">var</span> ar = HttpWebRequest.BeginGetResponse(asyncDriver.AsyncCallback);
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 1;
<span style="color: blue;">var</span> response = HttpWebRequest.EndGetResponse();
response.DoSomthing();
}</code></pre>
<br />
So we have AsyncDriver class. Pay attention to BeginGetResponse(), as you can see the call back function is offered by AsyncDriver. When BeginGetResponse() finished its work, AsyncDriver will take control, and it drive the async steps in Foo() by calling iterator.MoveNext(). The 'iterator' is from Foo().<br />
<br />
That explains the theory of driving async steps of an IEnumerable function. Real code would be more complex.<br />
<br />
Here is the complete code of AsyncDriver. And follow that is the usage of AsyncDriver.<br />
<br />
<span style="background-color: white; color: blue; font-family: Consolas, 'Courier New', Courier, monospace; font-size: 10pt;">using</span><span style="background-color: white; font-family: Consolas, 'Courier New', Courier, monospace; font-size: 10pt;"> System;</span><br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"><span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Text;
<span style="color: blue;">using</span> System.Threading;
<span style="color: blue;">namespace</span> Common
{
<span style="color: blue;">public</span> <span style="color: blue;">class</span> AsyncDriver
{
<span style="color: blue;">private</span> <span style="color: blue;">class</span> AsyncDriverResult : IAsyncResult
{
<span style="color: blue;">private</span> <span style="color: blue;">object</span> asyncState;
<span style="color: blue;">public</span> <span style="color: blue;">object</span> AsyncState
{
<span style="color: blue;">get</span> { <span style="color: blue;">return</span> asyncState; }
<span style="color: blue;">set</span> { asyncState = value; }
}
<span style="color: blue;">public</span> WaitHandle AsyncWaitHandle
{
<span style="color: blue;">get</span> { <span style="color: blue;">throw</span> <span style="color: blue;">new</span> NotImplementedException(); }
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> CompletedSynchronously
{
<span style="color: blue;">get</span> { <span style="color: blue;">throw</span> <span style="color: blue;">new</span> NotImplementedException(); }
}
<span style="color: blue;">private</span> <span style="color: blue;">bool</span> isCompleted;
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsCompleted
{
<span style="color: blue;">get</span> { <span style="color: blue;">return</span> isCompleted; }
<span style="color: blue;">set</span> { isCompleted = value; }
}
}
<span style="color: blue;">private</span> AutoResetEvent executionFinishedEvent;
<span style="color: blue;">private</span> Mutex mutex;
<span style="color: blue;">private</span> AsyncDriverResult asyncDriverResult;
<span style="color: blue;">private</span> AsyncCallback AsyncDriverCallback;
<span style="color: blue;">private</span> Exception terminationException;
<span style="color: blue;">private</span> IEnumerable<<span style="color: blue;">int</span>> enumerable;
<span style="color: blue;">private</span> IEnumerator<<span style="color: blue;">int</span>> iterator;
<span style="color: blue;">public</span> <span style="color: blue;">delegate</span> IEnumerable<<span style="color: blue;">int</span>> AsyncEnumerator(AsyncDriver asyncDriver, <span style="color: blue;">object</span> state);
<span style="color: blue;">public</span> AsyncDriver()
{
mutex = <span style="color: blue;">new</span> Mutex();
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> AsyncCallback(IAsyncResult ar)
{
DriveToNext();
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> DriveToNext()
{
ThreadPool.QueueUserWorkItem((aeObject) =>
{
mutex.WaitOne();
<span style="color: blue;">try</span>
{
<span style="color: blue;">bool</span> tonext = iterator.MoveNext();
<span style="color: blue;">if</span> (tonext)
{
<span style="color: blue;">if</span> (iterator.Current == 0)
{
OnExecutionFinished();
}
}
<span style="color: blue;">else</span>
{
OnExecutionFinished();
}
}
<span style="color: blue;">catch</span> (Exception ex)
{
terminationException = ex;
ex.Data.Add(<span style="color: #a31515;">"PtolemaicCallStack"</span>, ex.StackTrace);
OnExecutionFinished();
}
<span style="color: blue;">finally</span>
{
mutex.ReleaseMutex();
}
},
<span style="color: blue;">this</span>);
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> OnExecutionFinished()
{
iterator.Dispose();
executionFinishedEvent.Set();
AsyncDriverCallback(asyncDriverResult);
}
<span style="color: blue;">public</span> IAsyncResult BeginExecute(AsyncEnumerator asyncEnumerator, AsyncCallback callback, <span style="color: blue;">object</span> state)
{
asyncDriverResult = <span style="color: blue;">new</span> AsyncDriverResult();
asyncDriverResult.AsyncState = state;
enumerable = asyncEnumerator(<span style="color: blue;">this</span>, state);
AsyncDriverCallback = callback;
Execute();
<span style="color: blue;">return</span> asyncDriverResult;
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> EndExecute(IAsyncResult ar)
{
executionFinishedEvent.WaitOne();
<span style="color: blue;">if</span> (terminationException != <span style="color: blue;">null</span>)
{
<span style="color: blue;">throw</span> terminationException;
}
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> Execute()
{
executionFinishedEvent = <span style="color: blue;">new</span> AutoResetEvent(<span style="color: blue;">false</span>);
iterator = enumerable.GetEnumerator();
DriveToNext();
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> DumpException(Exception ex)
{
<span style="color: blue;">string</span> msg = <span style="color: #a31515;">"\n=================================================================\n"</span>
+ ex.ToString() + <span style="color: #a31515;">"\n"</span>
+ ex.Message + <span style="color: #a31515;">"\n\n"</span> + ex.StackTrace + <span style="color: #a31515;">"\n"</span>;
<span style="color: blue;">if</span> (ex.Data.Contains(<span style="color: #a31515;">"PtolemaicCallStack"</span>))
{
msg += <span style="color: #a31515;">"\n---- PtolemaicCallStack ----\n"</span> + ex.Data[<span style="color: #a31515;">"PtolemaicCallStack"</span>];
}
msg += <span style="color: #a31515;">"\n=================================================================\n"</span>;
<span style="color: blue;">return</span> msg;
}
}
}
</code></pre>
<br />
<br />
The usage of AsyncDriver:<br />
<br />
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"> <span style="color: blue;">public</span> <span style="color: blue;">void</span> Main()
{
Common.AsyncDriver asyncDriver = <span style="color: blue;">new</span> Common.AsyncDriver();
<span style="color: blue;">var</span> serverContext = <span style="color: blue;">new</span> ServerContext();
serverContext.AsyncDriver = asyncDriver;
asyncDriver.BeginExecute(Foo, FooCallback, asyncDriver);
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> FooCallback(IAsyncResult ar)
{
<span style="color: blue;">var</span> asyncDriver = ar.AsyncState <span style="color: blue;">as</span> Common.AsyncDriver;
asyncDriver.EndExecute(ar);
}
<span style="color: blue;">private</span> IEnumerable<<span style="color: blue;">int</span>> Foo(Common.AsyncDriver asyncDriver, <span style="color: blue;">object</span> state)
{
<span style="color: blue;">var</span> ar = HttpWebRequest.BeginGetResponse(asyncDriver.AsyncCallback);
<span style="color: blue;">yield</span> <span style="color: blue;">return</span> 1;
<span style="color: blue;">var</span> response = HttpWebRequest.EndGetResponse();
response.DoSomthing();
}</code></pre>
<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com1tag:blogger.com,1999:blog-5512075233013839753.post-65547798121213331052013-10-18T20:35:00.000-07:002013-10-18T20:35:16.470-07:00[Windows Service Debugging] Separate code from service app for convenient debuggingDebugging a windows service is not as convenient as windows application as it states on this <a href="http://msdn.microsoft.com/en-us/library/aa984342(v=vs.71).aspx">MSDN document</a>.A simple way to improve debugging is to separate service function code from the service application to a DLL, and then create an normal windows application start the service object in DLL. Detailed steps as following:<br />
<br />
<br />
<ol>
<li>Create a windows service project that only has VS generated code in it.</li>
<li>Create a DLL proeject that contains the service object.</li>
<li>Let service project call the service object to start it.Then your service would work. But this is not for debugging.</li>
<li>Create a normal windows application, and just as the service project, just call the service object ans start it. This application is convenient for you to debug the service object.</li>
</ol>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-67263632730210591462013-09-25T18:01:00.001-07:002013-09-25T20:47:46.777-07:00(Visual Studio) Per configuration application icon settingFor some reason, I want to build several versions with small differences, i.e. different application icons for different customers. For example, icon1 for customer 1, and icon2 for customer 2.<br />
<br />
On Visual Studio 2010 UI, you can only the one icon for all configurations. But when you open .csproj file as plain text, you can see it's real powerful. All per configuration settings are under tag like this:<br />
<br />
<propertygroup condition="'$(Configuration)|$(Platform)' == 'PublicDebug|x86'"></propertygroup><br />
<br />
So just find <b><applicationicon>images\AppIcon.ico</applicationicon></b> that doesn't belong to your configuration, and add it to the configuration you want. All done!<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-83603135525402021092012-11-12T06:53:00.000-08:002016-02-05T19:12:29.814-08:00HTTPS Communication – HttpListener based Hosting and Client Certification<span style="font-family: "arial"; font-size: 15px;">KEYWORDS: HTTPS, SSL, HttpListener, X509Chain, X509Certificate2, makecert, OpenSSL, client certificate</span><br />
<span style="font-family: "arial"; font-size: 15px;"><br /></span>
<span style="font-family: "arial"; font-size: 15px;">(Just found, a wonderful tool set that could help you to host easily, http://katanaproject.codeplex.com/. The site referred my post, and I didn't realize till now :-) thanks for refering. [2016-2-6])</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<a href="http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">HttpListener</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">
is the easiest way for you to host an HTTP/HTTPS server. This article
provides you step-by-step instructions to create your own server and
authenticate clients based on client certificate from ground up in C#.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;"><a href="https://docs.google.com/open?id=0BwKD9xrjSqz0c0lwYjRnLWV5OU0">Download the sample code</a></span><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<br />
<h2>
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 1</span></h2>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Firstly, you should create your .net application and add these four lines.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var server = new HttpListener();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">server.Prefixes.Add("https://+:90/");</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">server.Start();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">HttpListenerContext context = server.GetContext();</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">These
fourlines will make your server started and listening on the port. Be
aware of the exceptions (HttpListenerException) thrown from the
invocation server.Start(), and see step 2 to solve it.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"><br /></span>
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 2</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Step
1 shows you it’s so easy to start a server. But wait, Start() throws an
exception (HttpListenerException: Access Denied, native error code 5,
HRESULT 80004005), if you run your app under non-privilege account. If
you want a non-privilege account to run the server, you have to add ACL<span style="background-color: white;"> (</span></span><span style="background-color: white; color: #222222; font-family: "arial"; font-size: 15px; vertical-align: baseline;">Access Control Lists)</span><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"> to the system. In command line:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">netsh http add urlacl url=https://+:80/MyUri user=DOMAIN\user</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Pay
attention to the parameter ‘user’. Put whatever user you want to assign
the start server right to here. If set the parameter user=users, it
will grant all user account (non-privileged) to start the app and listen
on the specific ip and port. The ip part ‘+’ stands for all IPs of your
machine. For the server you want to handle urls from root (e.g. </span><a href="http://localhost/"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">http://localhost/</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">), you don’t need ‘MyUri’ part, and your command is like this:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">netsh http add urlacl url=https://+:80/ user=DOMAIN\user</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"><br /></span>
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 3</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">And
then your app won’t throw any exception. Your app would be blocked at
server.GetContext() and waiting for incoming connections. Try the url
https://localhost:90/ in your browser, there is still an error page with
HTTP 101 ERR_CONNECTION_RESET. This because you haven’t assign a
certificate to the server and the browser can’t verify the validity of
the server. Remember we are visiting an HTTPS site. The server
certificate is a must.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">So, let’s create the certificates. You can either create your certificates by </span><a href="http://msdn.microsoft.com/en-us/library/bfsktky3%28v=vs.80%29.aspx"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">makecert</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"> or by </span><a href="http://www.openssl.org/"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">OpenSSL</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">. And this </span><a href="http://pages.cs.wisc.edu/~zmiller/ca-howto/"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">How to Setup a CA</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">
gives you an easy tutorial of creating certificates hierachy by
OpenSSL. First is the root CA certificate. For experimental cases,
makecert is enough. But for product, you may want to use OpenSSL or
apply a certificate from CA like VeriSign.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">makecert -n "CN=TestCA" -r -sv TestCA.pvk TestCA.cer</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">And import the root certificate to the system certificate storage of Rusted Root Certification Authority. See </span><a href="http://www.codeproject.com/Articles/25677/Simple-WCF-X509-Certificate"><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">this article</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Then create the certificate for your HTTPS web site.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">makecert -iv TestCA.pvk -n "CN=TestSite" -sv TestSite.pvk -ic TestCA.cer TestSite.cer -sr LocalMachine -ss My -sky exchange -pe</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">If
you will test your client app on a machine other than the server
machine, you have to import the TestCA.cer to the client machine as
well. So that the client machine trust TestCA (the root cert), it will
also trust the server certificate (TestSite).</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Hosting
an HTTPS site, you must have a certificate with private key. But the
last makecert command creates the private key in TestCA.pvk which can’t
be imported to the system storage directly. We have to convert it to
.pfx format:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">pvk2pfx -pvk "TestSite.pvk" -spc "TestSite.cer" -pfx "TestSite.pfx"</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Then you will see the certificate for your site:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><img height="41px;" src="https://lh5.googleusercontent.com/4u7c7z53btxCV8AkgTm6sVUpNkrUSMVLbjfgz5GolviqRwWje76tkUkSMVkX02T3oVNLjKqdQF1kfTcfoeniCCyGHukn6iqcughjtotWCjD8A8Dq6Fo" width="106px;" /><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 4</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">How
to use the server certificate? At this point, the when client connect
to the server, the client will throw an exception (WebException The
underlying connection was closed: An unexpected error occurred on a
send), simply because the server doesn’t use the certificate yet. To
resolve the exception,just binding the certifiate to the server’s ip and
port by netsh.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">netsh
http add sslcert ipport=0.0.0.0:90
appid={61047666-992C-4137-9303-7C01781B054E}
certhash=75d0fed71881f2141b5b6cb24801dfa554439b1c
clientcertnegotiation=enable</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">‘0.0.0.0’
in the ipport parameter means every ip of this machine would be
assigned with the certificate. The parameter appid is your application
id. You can see it in the project property, the ‘Application’ page, and
the dialog poped up by clicking ‘Assembly Information’ button. The
parameter ‘clientcertnegotiation=enable’ will allows C/S mutually
authentication based on certificates, i.e. server side could verfiy the
certificate validation of the client side as well as the client side
verifying the server side. If you don’t want verification for client
side, just omit the parameter.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"><br /></span>
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 5</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Visit</span><a href="https://localhost:90/"><span style="color: black; font-family: "arial"; font-size: 15px; vertical-align: baseline;"> </span><span style="color: #1155cc; font-family: "arial"; font-size: 15px; vertical-align: baseline;">https://localhost:90/</span></a><span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">
again, your browser will warning you that the site is not the owner of
the certificate. It’s because we don’t have a domain for our
experimental site and no domain name was set into the certificate. So
just click continue to view the page and the browser will show you a
blank page.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"> </span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Let’s add responding code to the server side, so that we can see something on the page.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">string message = "Hello World!";</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var buffer = System.Text.Encoding.UTF8.GetBytes(message);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">context.Response.OutputStream.Write(buffer, 0, buffer.Length);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">context.Response.OutputStream.Close();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">Now the page displays “Hello World!”.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"><br /></span>
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 6</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">We
have done the work of constructing server side. The server can show its
identity by providing its certificate and client can verify it. Client
still shows no certificate to the server. In some cases, the server need
to verify the client’s identity, and only when the client is valid
(e.g. a valid member of some organization) the server would start data
communication. In this case, a client app (other than web browser) is a
must. So let’s create a client app.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Here is the basic client code without client certificate.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">ServicePointManager.ServerCertificateValidationCallback =</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> new RemoteCertificateValidationCallback(CheckValidationResult);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: 15px; vertical-align: baseline;"></span><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">string url = "https://localhost:90/";</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">Console.WriteLine("Visiting " + url);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">HttpWebRequest objRequest = System.Net.HttpWebRequest.Create(url) as HttpWebRequest;</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">objRequest.ProtocolVersion = HttpVersion.Version10;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: 15px; vertical-align: baseline;"></span><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var response = objRequest.GetResponse();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var responseReader = new StreamReader(response.GetResponseStream());</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var responseContent = responseReader.ReadToEnd();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">Console.WriteLine("Server replied: " + responseContent);</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">CheckValidationResult
is a callback function which allows you to perform customized
validation against server certificate, returns true to accept the
certificate. As expected, the client gets the server reply: “Hello
World!”.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"><br /></span>
<br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 7</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Here
we add client certification code. Basically you have two ways of
creating a X509Certificate2 which could contain public/private key pair.
Other ways like manipulating public/private key pair raw data directly,
may be tricky and complex.</span><br />
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li style="font-family: Arial; font-size: 15px; list-style-type: decimal; vertical-align: baseline;"><span style="vertical-align: baseline;">Load .pfx from file;</span></li>
<li style="font-family: Arial; font-size: 15px; list-style-type: decimal; vertical-align: baseline;"><span style="vertical-align: baseline;">Load certificate with private key from the system’s certificate store.</span></li>
</ol>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Here is the first one, load from file:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">HttpWebRequest objRequest = System.Net.HttpWebRequest.Create(url) as HttpWebRequest;</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">X509Certificate2 clientCertificate = new X509Certificate2("TestClient.pfx", "the key password");</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">objRequest.ClientCertificates.Add(clientCertificate);</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">You
have to add certificate to the https request right after you created
the request, because GetResponse() will use the certificate immediately.
Here is the second way of creating X509Certificate2 - loading the
certificate from the system store:</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">static X509Certificate2 LoadClientCertificate()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> // Note: Change "My" and StoreLocation.CurrentUser to where your certificate stored.</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> var store = new X509Store("My", StoreLocation.CurrentUser);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, "TestClient", true);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> if (certificates.Count != 0)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> return null;</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: 15px; vertical-align: baseline;"></span><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> return certificates[0];</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">}</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Before
running it, you have to import the certificate (with private key) to
the store just like you did with the server certificate. Loading a
certificate (without private key) can be done by a non-privileged
account, while accessing private key of a certificate from the system
store requires administrator privilege. So when you run above code by a
non-privileged account, you will get the certificate although, but only
public key is in it. While the server side needs the client to sign
something to verify the client’s identity, so the client must have the
private key. So when carrying out further steps of HTTPS communication</span><br />
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li style="font-family: Arial; font-size: 15px; list-style-type: decimal; vertical-align: baseline;"><span style="vertical-align: baseline;">When the client certificate loaded from system store, the client code will get an WebException;</span></li>
<li style="font-family: Arial; font-size: 15px; list-style-type: decimal; vertical-align: baseline;"><span style="vertical-align: baseline;">When the client cerfiticate loaded from file, the server will get no client cert (GetClientCertificate() returns null).</span></li>
</ol>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Loading from store and loading from file both has pros and cons.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<h3 dir="ltr">
<span style="font-family: "arial"; font-size: 16px; vertical-align: baseline;">STEP 8</span></h3>
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">Server side still doesn’t verify the client certificate. So let’s add the code logic.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">HttpListenerContext context = server.GetContext();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-size: 15px; vertical-align: baseline;"></span><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">var clientCertificate = context.Request.GetClientCertificate();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">X509Chain chain = new X509Chain();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">chain.Build(clientCertificate);</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">if (chain.ChainStatus.Length != 0)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> // Invalid certificate</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;"> context.Response.OutputStream.Close();</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: 15px; vertical-align: baseline;">}</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;">X509Chain
is a tool which builds the chain of trust of the certificate. If the
certificate is invalid, then you can find error information in
chain.ChainStatus. You can implement detailed logic upon X509Chain
rather than only checking chain.ChainStatus.Length. Set RevocationMode
to NoCheck because we don’t have a certificate server to tell you
whether a certificate is revoked.</span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />
<span style="font-family: "arial"; font-size: 15px; vertical-align: baseline;"></span><br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com16tag:blogger.com,1999:blog-5512075233013839753.post-29812307757280206952012-08-22T20:07:00.001-07:002012-08-23T20:26:28.931-07:00Render English and Chinese with mono font(This is an unresolved issue)<br />
<br />
How to make a Chinese character exactly 2 English characters wide?<br />
<br />
I've tried it in WPF application with Courier New and Segoe UI Mono, but both failed. And also tried SimSun as fallback font, failed again.<br />
<br />
Here is the summary of my test.<br />
<b>Successful Examples</b><br />
Notepad<br />
Notepad++<br />
HTML with pre tag rendered by Chrome
<br />
<br />
<b>Failed Examples</b><br />
Visual Studio 2010<br />
HTML without pre tag rendered by Chrome
<br />
HTML with and without pre tag rendered by IE
<br />
<br />
I tried Courier New and Segoe UI Mono with fallback font SimSun in my WPF app. The fallback font mechanism worked, because it can render STLiti which is 隶书, see below<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCFYlbXmCS4olLXk_H8N7TBZtvHDV9ekdka-IugRotOaa7yLdIGgNZzBe8lE_odBjHdItE89pdVNIxNPP-CQq565qqt7Io6ILQNna8RGtTFrqzzCNDU6s93VFoAwG8F3_YfPSDQGBhF5fA/s1600/Segoe+UI+Mono+and+STLiti.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCFYlbXmCS4olLXk_H8N7TBZtvHDV9ekdka-IugRotOaa7yLdIGgNZzBe8lE_odBjHdItE89pdVNIxNPP-CQq565qqt7Io6ILQNna8RGtTFrqzzCNDU6s93VFoAwG8F3_YfPSDQGBhF5fA/s1600/Segoe+UI+Mono+and+STLiti.jpg" /></a></div>
<br />
One Chinese char is a little bit less than 2 English chars in width. when fallback font is SimSun, it's the same case<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglQlsMyGPljDpCmD0-MfH1Kl2v5pmxik5GNoSAH45gTzLiahOEvtVo9ebVURRMQir3-3uPAJIXvTsq-wwF51Ly6PXD5q_2T0aTp53KP3eXnMjLYVoLCAtHmYTc3yWQl_hSo64ztq-LcVVV/s1600/Segoe+UI+Mono+and+SimSun.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglQlsMyGPljDpCmD0-MfH1Kl2v5pmxik5GNoSAH45gTzLiahOEvtVo9ebVURRMQir3-3uPAJIXvTsq-wwF51Ly6PXD5q_2T0aTp53KP3eXnMjLYVoLCAtHmYTc3yWQl_hSo64ztq-LcVVV/s1600/Segoe+UI+Mono+and+SimSun.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Figure 1</div>
<br />
Visual Studio has the same issue<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0Rwz3gapr5tOaH9yk7qOJWdne6THS8Pt7iHHlcIBZIdoLqOBNM0Xt2HA8rfwuwmjhDWmksro3brxYDRv6FEOqoCnTAKmWBK69fNw4CVQpSsm-3bV5439F2qewWUi5SAUI5tVmCwHZTJ5i/s1600/Courier+New+in+Visual+Studio.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0Rwz3gapr5tOaH9yk7qOJWdne6THS8Pt7iHHlcIBZIdoLqOBNM0Xt2HA8rfwuwmjhDWmksro3brxYDRv6FEOqoCnTAKmWBK69fNw4CVQpSsm-3bV5439F2qewWUi5SAUI5tVmCwHZTJ5i/s1600/Courier+New+in+Visual+Studio.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Figure 2</div>
<br />
While Notepad++ is pretty successful<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBRziXGmuwfMbPUF-oAhGbTIDHzY9TZV_WpNl-65079N_MKC-9iDqCYcj3n7bQkiN7xbjCcapRzKoNIeaPfz2Jyvx55MP0mMr_JlLNyR55LTVC7Dzym3_-UJBzoZsf9vpNobhm_igEchwT/s1600/Segoe+UI+Mono+in+NotepadPlusplus.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBRziXGmuwfMbPUF-oAhGbTIDHzY9TZV_WpNl-65079N_MKC-9iDqCYcj3n7bQkiN7xbjCcapRzKoNIeaPfz2Jyvx55MP0mMr_JlLNyR55LTVC7Dzym3_-UJBzoZsf9vpNobhm_igEchwT/s1600/Segoe+UI+Mono+in+NotepadPlusplus.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Figure 3</div>
<br />
Different web browser has different behavior. With <br />
<pre> tag would work well in Chrome while it can't give you Chinese char of 2 English chars width without
<br />
<pre>. And IE can't do it in both cases.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR55HLfrKI6sQtl41bbiR3fhdeFrox6YkRrcjAtSdUmLPgsDprHJueVhp8fOsdQGMoN7p9wJCYGKztMSnP80JDqURRPE6qh27Nbad-tWOf7turhDWQFFQiuD7PMHhWDZ6fM9myq_3jnQMG/s1600/HTML.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR55HLfrKI6sQtl41bbiR3fhdeFrox6YkRrcjAtSdUmLPgsDprHJueVhp8fOsdQGMoN7p9wJCYGKztMSnP80JDqURRPE6qh27Nbad-tWOf7turhDWQFFQiuD7PMHhWDZ6fM9myq_3jnQMG/s1600/HTML.jpg" /></a></div>
<br />
<br />
As you can see Chinese chars in Figure 3 is a little bit wider than Chinese chars in Figure 1. Is there a covered mechanism results narrow Chinese chars?<br />
<br />Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com1tag:blogger.com,1999:blog-5512075233013839753.post-89782229632497258632012-03-06T23:15:00.002-08:002012-03-06T23:24:35.133-08:00Config Test Deployment for VS2010The MSDN document How to: Config Test Deployment is somewhat out-dated. <b style="font-family: 'Segoe UI', Verdana, Arial; font-size: 13px; "><run config="" file="" name="">.testrunconfig</run></b> in VS2010 is actually local.testsettings. Another config file 'TraceAndTestImpact.testsettings' really fooled me. ^_^Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-79057499477944845662011-06-12T07:19:00.000-07:002011-06-13T20:06:41.481-07:00Mean-shift Object Tracking Study Notes<p>Xueqing Sun</p> <p><a href="mailto:sunshaking@gmail.com">sunshaking@gmail.com</a></p> <p>June 12<sup>th</sup>, 2011</p> <p><a href="http://creativecommons.org/licenses/by/3.0">License CC BY <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002[4]" border="0" alt="clip_image002[4]" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-B7acsyxDjs6MDRQjgATY4VvN6-JllEq7futvdJ3i_rjQUMKbm_NS72Plv9USc0fp8czvtro5E9qoEURXBZg1Ioxdq25S7aKt_29wdnLtkWMfJOs-1yRzCrGRpbwdplz8m5YZqhChy7e_/?imgmax=800" width="54" height="19" /></a></p> <p><i>You can distribute, remix, tweak, and build upon this work, even commercially, as long as you credit Xueqing Sun for the original creation.</i><i></i></p> <p>I was reading a book, ‘Image Processing, Analysis, and Machine Vision, Milan Sonka, Vaclav Hlavac, Roger Boyle’ for studying mean-shift object tracking algorithm. But the book was really hard to understand, especially for a beginner of machine vision. Yesterday, with the help of Guangwei, a friend of mine (he is a scientist at National Astronomical Observatories, Chinese Academy of Science), I finally understood the algorithm. And I would like to explain what I understood for sake of helping other guys who are still struggling on this algorithm.</p> <p><b>Heads up Questions</b></p> <p>1. What is the probability density function of an image?</p> <p>2. How does the density function contribute to target model?</p> <p>3. What’s kernel function? How does it work?</p> <p> </p> <p>Here is the summary of the algorithm</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8uU0Hg0Zlh4xdApX92RfInGe2gOJFzDXHGTd6mKaHdvmCm2UKdFQUY5c9wU_BGHnL9LGykwI9OU7fv9nNVojVZ2YGdmOyrH7zm-N7w_zy1oLFfhR5nMsSJ8KPIiLqsLab8p5NMK_6B4nP/s1600-h/image%25255B55%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg52K-P3G4l-8vi5p15aEh-1PvnoG7CEjFQROfS7rLxt66ujJZ0rFz-s3YutatKzHXWltItJgA1g5-bdD4qI1NbjdArfbxGkFksNUjBEoHdusxBElhnM8p0KbdkTFopyFQjHOrKY0_qiOlF/?imgmax=800" width="523" height="476" /></a></p> <p>To locate a target on an image, we must have a target model, an image which contains the target. The goal of mean-shift algorithm is to tell you the position of your target on the image. Suppose we have a target model image with 5*5 pixels. The pixel values listed below: <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="45"> <p>x</p> </td> <td valign="top" width="45"> <p>y</p> </td> <td valign="top" width="45"> <p>pixel</p> </td> </tr> <tr> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>1</p> </td> </tr> <tr> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>1</p> </td> </tr> <tr> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>6</p> </td> </tr> <tr> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>5</p> </td> </tr> <tr> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>7</p> </td> </tr> <tr> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>0</p> </td> </tr> <tr> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>4</p> </td> </tr> <tr> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>7</p> </td> </tr> <tr> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>0</p> </td> </tr> <tr> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>4</p> </td> </tr> <tr> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>3</p> </td> </tr> <tr> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>5</p> </td> </tr> <tr> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>7</p> </td> </tr> <tr> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>1</p> </td> </tr> <tr> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>5</p> </td> </tr> <tr> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>7</p> </td> </tr> <tr> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>0</p> </td> </tr> <tr> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>9</p> </td> </tr> <tr> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>9</p> </td> </tr> <tr> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>2</p> </td> </tr> <tr> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>0</p> </td> <td valign="top" width="45"> <p>0</p> </td> </tr> <tr> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>1</p> </td> <td valign="top" width="45"> <p>1</p> </td> </tr> <tr> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>2</p> </td> <td valign="top" width="45"> <p>4</p> </td> </tr> <tr> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>3</p> </td> <td valign="top" width="45"> <p>3</p> </td> </tr> <tr> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>4</p> </td> <td valign="top" width="45"> <p>3</p> </td> </tr> </tbody></table> </p> <p>Target model image</p> <p>The row x and y are the location of a pixel on the image. And the third row ‘pixel’ is the value. For convenient purpose, we limit pixel value from 0 to 9. Now we can create a frequency table like below. Normally images are colored, but we simplified the problem from colored images to gray scale images. A colored image can be considered as a composition of three gray scale images. So the rationale explained here can be easily applied to colored images. <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="73"> <p>bin</p> </td> <td valign="top" width="73"> <p>q</p> </td> </tr> <tr> <td valign="top" width="73"> <p>1</p> </td> <td valign="top" width="73"> <p>8</p> </td> </tr> <tr> <td valign="top" width="73"> <p>2</p> </td> <td valign="top" width="73"> <p>1</p> </td> </tr> <tr> <td valign="top" width="73"> <p>3</p> </td> <td valign="top" width="73"> <p>3</p> </td> </tr> <tr> <td valign="top" width="73"> <p>4</p> </td> <td valign="top" width="73"> <p>3</p> </td> </tr> <tr> <td valign="top" width="73"> <p>5</p> </td> <td valign="top" width="73"> <p>3</p> </td> </tr> <tr> <td valign="top" width="73"> <p>6</p> </td> <td valign="top" width="73"> <p>1</p> </td> </tr> <tr> <td valign="top" width="73"> <p>7</p> </td> <td valign="top" width="73"> <p>4</p> </td> </tr> <tr> <td valign="top" width="73"> <p>8</p> </td> <td valign="top" width="73"> <p>0</p> </td> </tr> <tr> <td valign="top" width="73"> <p>9</p> </td> <td valign="top" width="73"> <p>2</p> </td> </tr> </tbody></table> </p> <p>Frequency</p> <p>The frequency means how many pixels located in a specific bin. For example, the first row means there are 8 pixels which values are less or equal to ‘1’. Furthermore we can have histogram chart for the table.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpEWPgu5D9NPzIXEaPm-7Z7TEONPRTcKDl32nELa50592hVRInpirqYgq3GRewSBILTSUNFdM4s4UwX5tV-BeGz3kCOVq2tSWDtIwmMGD6cy5B4zt7jMUpBiHY7C2GNAPTzCcv9Lr8Jf1c/s1600-h/image%25255B57%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu3iixhjFLGeT1ySsYkEMW93lfN9-GmJhI0v3zj3TBXvpSN3sHB-agiMvbmrpplsqyl3vdx0-z5f8DWgehBrvYGfIuu43DDPYrmLkjNWVcb8rLQ0e0sO2PBv4z1casw0eKjDPussvRhLPF/?imgmax=800" width="507" height="318" /></a></p> <p>Histogram</p> <p>On the book, and many other materials, the density function of target model, defined as below: <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh4.ggpht.com/-UERF_N_XYwA/TfSyIwHQuFI/AAAAAAAAF_Q/_M_7yU0nfyo/s1600-h/image%25255B58%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-ImZ7Qn4U3Ho/TfSyMcz6tmI/AAAAAAAAF_U/VblxJLXJ-ng/image_thumb%25255B36%25255D.png?imgmax=800" width="174" height="61" /></a></p> </td> <td width="32"> <p>1</p> </td> </tr> </tbody></table> </p> <p>The density function is closely related with the frequency table. Here the black <a href="http://lh3.ggpht.com/-e3s7Cweqx58/TfSyRKGOlSI/AAAAAAAAF_Y/AqDKigQL9CY/s1600-h/image%25255B63%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-5b6odwmHmw0/TfSyV_jYDBI/AAAAAAAAF_c/7JbQvN78nmg/image_thumb%25255B39%25255D.png?imgmax=800" width="11" height="16" /></a><b> </b>is a vector which has m components. In this case, the m is 9 because we have 9 bins. Each component is made from corresponding bin. Let look into the component definition. <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjG0U7xEbVzRgRNmYzdmMHhGvIf9K11VHAo4fDYoJgANIelptUxK_mPoQz5VGPjvrtD3AiE6q17mlPL2NNqmhXpEO9vN4WXcV4xq0eTuG9RetXyiD0dOhFjkgYiB4Xa6VOuRMZVs2UUjQO/s1600-h/image%25255B59%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg41R1E5rgTj9Mf3oSpPoafUUbMgw_DqmOE_x-h85re7rUYVGZ71miTE3Ia08mFmaLV8B-ZN5Ot4ZZFiI0YjACFyrpm4IxDscrLdn6RNLp8seY9H0lYmnVmT3IZVLz-lmck_gAGHr36pzgV/?imgmax=800" width="232" height="58" /></a></p> </td> <td width="32"> <p>2</p> </td> </tr> </tbody></table> </p> <p>The definition looks somewhat complex. Let’s split it into parts so we can understand it easier. First, let’s see the delta part <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh5.ggpht.com/-GuwmxmQXnOQ/TfSyjJuocSI/AAAAAAAAF_o/LMfzS80FlSE/s1600-h/image%25255B32%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-xe-uI1-fsz4/TfSyonPQ_lI/AAAAAAAAF_s/q-anTmjmB9k/image_thumb%25255B16%25255D.png?imgmax=800" width="180" height="28" /></a></p> </td> <td width="32"> <p>3</p> </td> </tr> </tbody></table> </p> <p>n is the pixel number. In this case we have 25 pixels. So the n is 25. <a href="http://lh3.ggpht.com/-wQRR54mKzLQ/TfSyq71HYdI/AAAAAAAAF_w/QP-4LN-FMdo/s1600-h/clip_image015%25255B4%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image015[4]" border="0" alt="clip_image015[4]" src="http://lh4.ggpht.com/-JKhR1r4zoK8/TfTB_0rUnXI/AAAAAAAAF_0/eC5qy2pTJZU/clip_image015%25255B4%25255D_thumb.gif?imgmax=800" width="13" height="18" /></a> is the coordinate of i<sup>th</sup> pixel in the image. For example, the first pixel coordinate is (0,0), and the second is (0,1). u means we are currently defining u<sup>th</sup> component corresponding to u<sup>th</sup> bin. Function <a href="http://lh6.ggpht.com/-0gTCH3VFPa0/TfTCB18qr1I/AAAAAAAAF_4/n5jxRsLxA0o/s1600-h/clip_image017%25255B4%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image017[4]" border="0" alt="clip_image017[4]" src="http://lh5.ggpht.com/-nbq_jmh_kGo/TfTCaBnAV-I/AAAAAAAAF_8/z5FWw2AydaA/clip_image017%25255B4%25255D_thumb.gif?imgmax=800" width="34" height="18" /></a> tells which bin the pixel <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOx9sv1qI_9JGsZbd3igDLDkwhL1nFIwVCHzrwD0uPiWkgqWfhlKW0J9jaDS8MoSv1y2WdmUjyJnHV88Uk8pNIy8Tl4T7jvGsO7DjQ45TUJ_8WpvlUprLJRU4XMLuViRE1THdDUyhx-bS0/s1600-h/clip_image019%25255B6%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image019[6]" border="0" alt="clip_image019[6]" src="http://lh3.ggpht.com/-QcXwpXumcJc/TfTCoL0u5aI/AAAAAAAAGAE/__LagQMXC0A/clip_image019%25255B6%25255D_thumb.gif?imgmax=800" width="14" height="18" /></a> go. For example, the first pixel (0,0) is 1, so it goes to bin 1, i.e. <a href="http://lh3.ggpht.com/-bLXM3jAjQ4o/TfTLBWMpcMI/AAAAAAAAGAI/082ONdy-oJs/s1600-h/clip_image021%25255B4%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image021[4]" border="0" alt="clip_image021[4]" src="http://lh3.ggpht.com/-Kxm3fwHKiTA/TfTLI7P3bKI/AAAAAAAAGAM/uWlfbd8w8YE/clip_image021%25255B4%25255D_thumb.gif?imgmax=800" width="67" height="17" /></a>.</p> <p>Actually, the formula 3 is a vector, let’s rewrite it as following: <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh5.ggpht.com/-D1dE9KSs9VY/TfTLNZOP57I/AAAAAAAAGAQ/MyF0YCpqj-g/s1600-h/image%25255B31%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-qWLT1ZdLJXQ/TfTLRCjuxqI/AAAAAAAAGAU/4BFuXDYniDE/image_thumb%25255B15%25255D.png?imgmax=800" width="223" height="29" /></a></p> </td> <td width="32"> <p>4</p> </td> </tr> </tbody></table> </p> <p>The delta function gives you 1 if the pixel <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9aWwxcoXXuYgtWfgm61PEdHRYUReaHezPZC7S5gmG9GKQ3lMxcYh3tq4GtBIbZvCFWomsS3KYEqcMRkhUVEK4tTY-GJDfgb2VxvY2c9cGP7tyIEm1VV0AyrWACQguq5rAlFAdEiRUiq8i/s1600-h/clip_image019%25255B7%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image019[7]" border="0" alt="clip_image019[7]" src="http://lh6.ggpht.com/-bVcCBdkoQKo/TfTLYuMDSTI/AAAAAAAAGAc/OHtdKS__K_s/clip_image019%25255B7%25255D_thumb.gif?imgmax=800" width="14" height="18" /></a> goes to bin u, otherwise it gives 0. So this vector works just like a mask. On the mask there are ‘1’s mark the pixels go to bin u. For example, if our image is 4*4, we might get a <b>D</b> vector like this: <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top"> <p>1</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>1</p> </td> </tr> <tr> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>1</p> </td> <td valign="top"> <p>1</p> </td> <td valign="top"> <p>0</p> </td> </tr> <tr> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>1</p> </td> </tr> <tr> <td valign="top"> <p>1</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>0</p> </td> <td valign="top"> <p>0</p> </td> </tr> </tbody></table> </p> <p>The image is a matrix. <b>D</b> is a vector. Just put each row of the matrix to one row in sequence then we’ll get <b>D</b>.</p> <p><b>IMPORTANT</b></p> <blockquote> <p><u>What’s the relationship between <b>D</b> and the frequency table?</u> The answer is for each u, <a href="http://lh4.ggpht.com/-szP3SZLzSM0/TfbQNhtniiI/AAAAAAAAGBQ/KlbACFS7Paw/s1600-h/image%25255B17%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-KmAnl5mG_3c/TfbQPnayaTI/AAAAAAAAGBU/AwZHtkxbcME/image_thumb%25255B13%25255D.png?imgmax=800" width="88" height="20" /></a>. Actually we can form feature space only based on <b>D</b>, because D already represents the image in statistics way. So mean-shift algorithm is so called an algorithm that based on probability density function. But marginal pixels are unstable, so the kernel function which is a weight function does the work. It give marginal pixels less weight to make the objective function in optimization process more stable.</p> </blockquote> <p> </p> <p>OK, let’s see another part of formula 2. It’s <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh6.ggpht.com/-OAuBykazFcg/TfTLeMnR1hI/AAAAAAAAGAg/1rI9XpTFJww/s1600-h/image%25255B33%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-MJ6lJyVkqW8/TfTLg0ivxwI/AAAAAAAAGAk/lyZL8MVXShI/image_thumb%25255B17%25255D.png?imgmax=800" width="202" height="34" /></a></p> </td> <td width="32"> <p>5</p> </td> </tr> </tbody></table> </p> <p>Again it’s a vector. Function k is the kernel function which actually is a weight function giving each pixel position a weight. So <a href="http://lh6.ggpht.com/-Uyc9y7b8u18/TfTLk0Xe7xI/AAAAAAAAGAo/GkrbHsPWneY/s1600-h/clip_image027%25255B4%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image027[4]" border="0" alt="clip_image027[4]" src="http://lh6.ggpht.com/-HhMqTmh5vw0/TfTLpYMkrEI/AAAAAAAAGAs/hQjGZBvHPGE/clip_image027%25255B4%25255D_thumb.gif?imgmax=800" width="16" height="17" /></a> can be defined as below:<b></b> <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh4.ggpht.com/-k1nelOBcnEI/TfTLqusB9wI/AAAAAAAAGAw/vlwYCAIJkPw/s1600-h/image%25255B39%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-S1P1jlk4FQg/TfTLvdCcZ_I/AAAAAAAAGA0/9eYkdfpdUTw/image_thumb%25255B21%25255D.png?imgmax=800" width="89" height="24" /></a></p> </td> <td width="32"> <p>6</p> </td> </tr> </tbody></table> </p> <p>It looks beautiful. I really hate <a href="http://lh5.ggpht.com/-BzbghmRudWE/TfTLzB6IHvI/AAAAAAAAGA4/XR79Y_hxubY/s1600-h/clip_image031%25255B4%25255D%25255B2%25255D.gif"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image031[4]" border="0" alt="clip_image031[4]" src="http://lh4.ggpht.com/-c7OhT6PDihk/TfTL39WgGSI/AAAAAAAAGA8/9klcf6VgZA0/clip_image031%25255B4%25255D_thumb.gif?imgmax=800" width="17" height="17" /></a> which makes formula unreadable.</p> <p>OK, now we get the density function of target model image. The candidate density function is pretty similar.<b></b> <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="536"> <p><a href="http://lh3.ggpht.com/-RVRH23_JHS8/TfTL5hk0CJI/AAAAAAAAGBA/evFyPuLc1Fo/s1600-h/image%25255B49%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-AzDS8xm1hwY/TfTL9j9-PZI/AAAAAAAAGBE/YigOKYqS4pA/image_thumb%25255B27%25255D.png?imgmax=800" width="210" height="58" /></a></p> </td> <td width="32"> <p>7</p> </td> </tr> <tr> <td valign="top" width="536"> <p><a href="http://lh4.ggpht.com/-v0aux6L_eC8/TfTMCrI9HKI/AAAAAAAAGBI/vowE5Dh-BoI/s1600-h/image%25255B48%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-R-AvmyMoKfQ/TfTME85rVCI/AAAAAAAAGBM/1O8W0DWQzd4/image_thumb%25255B26%25255D.png?imgmax=800" width="303" height="66" /></a></p> </td> <td width="32"> <p>8</p> </td> </tr> </tbody></table> </p> <p>Formula 8 is easier to understand because we’ve already understood formula 2. The k function in formula 8 is just a transformed version of original k.</p> <p>I think I’ve solved the hardest part of the mean-shift algorithm. And the rest of it would be much easier to understand because it is just kind of an optimism algorithm to find the <b>y</b>.</p> Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-78881062750091479312009-03-09T03:17:00.001-07:002009-03-09T04:05:35.922-07:00High Resolution Timer via Interop<p>Though Windows isn’t a real-time OS, we do need high resolution clocks and timers sometimes. .Net gives us Stopwatch class which is really a high resolution clock. But we can’t find a high resolution timer in .Net framework. A timer is different from a clock, which fires event periodically notifying you the period of time is up. This article is mainly to demonstrate the basic usage of interop. And a more complex and intensive material provided at the end of the article.</p> <p>There are high resolution timer services on Windows. But they are native APIs. Fortunately, we can use interop to call these native APIs.</p> <p>The first thing you have to do is to determine the device capabilities. Different devices have different resolutions<a href="http://www.geisswerks.com/ryan/FAQS/timing.html" target="_blank">[1]</a>. Some may give you 1 ms of resolution, but some may be 10 ms. And if you request a resolution that the device can’t support, an error will occur. To determine the resolution of the timer hardware, use timeGetTime().</p> <pre style="border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 100%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px"><code>[DllImport("winmm.dll")]<br />private static extern int timeGetDevCaps(ref TimerCaps caps, int sizeOfTimerCaps);</code></pre>TimerCaps is a struct. A C struct actually. We can use C# struct to map the data.<pre style="border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 100%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px"><code>[StructLayout(LayoutKind.Sequential)]<br />public struct TimerCaps<br />{<br /> /// <summary><br /> /// Minimum supported period in milliseconds.<br /> /// </summary><br /> public uint periodMin;<br /> /// <summary><br /> /// Maximum supported period in milliseconds.<br /> /// </summary><br /> public uint periodMax;<br />}</code></pre><p>Please keep in mind that “LayoutKind.Sequential” is essential, because it suppressed C# compiler from alter the order of the fields for optimization purpose. Here for the parameter “TimerCaps caps” we use “ref”, because we want the API to write some data into “caps”. The “ref” maps the type to the pointer of the type in C/C++. So “ref TimerCaps caps” means “TimerCaps *caps” in C/C++.</p><p>Now we can call the API.</p><pre style="border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 100%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px"><code>TimerCaps caps = new TimerCaps();<br />int ret = timeGetDevCaps(ref caps, Marshal.SizeOf(caps));</code></pre><p>And then we can start the timer.</p><pre style="border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 100%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px"><p><code>[DllImport("winmm.dll")]<br />private static extern int timeSetEvent(uint delay, uint resolution, MmTimerCallback proc, int user, int mode);<br />...<br />actuallPeriod = Math.Max(caps.periodMin, Period);<br />timeBeginPeriod(actuallPeriod);<br />timerId = timeSetEvent(1000/*delay*/, 0/*resolution*/, TimerCallback, 0, 1);</code></p></pre><p> “MmTimerCallback” is a delegate method mapping to callback function in C/C++. That’s almost the complete stuffs of the high resolution timer. Please be aware, the callback function will be called in a thread other than your main thread. You have to delegate the operation to your main thread if you want to access UI elements.</p><p>Here is a good read material talks about interop.</p><ul><li><a href="http://msdn.microsoft.com/en-us/magazine/cc164123.aspx" target="_blank">Calling Win32 DLLs in C# with P/Invoke</a> - Jason Clark</li></ul> Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-35671190475557202712008-12-17T19:38:00.000-08:002009-01-13T02:17:59.432-08:00The Way of Quitting an Application<p>There are several ways of letting an application to quit programmatically. But you should choose the best one among them.</p> <h2></h2> <h5>Environment.Exit Method</h5> <p>This method will force a process to terminate. So the process has no chance to do cleaning up work. No code after Environment.Exit will be executed. Any data that is unsaved will be lost. Not recommend this way.</p> <h5>Process.Kill Method</h5> <p>Killing a process just like Environment.Exit, terminates the process immediately and the process doesn't have the last chance to breath. So again, it's not recommended.</p> <h5>Process.CloseMainWindow Method</h5> <p>This method will send a request to a process' message loop, if the process does have a message loop. The process thus has a chance to do cleaning up work, and save unsaved data to disk then terminates gracefully. This method can be called either from another process or within the process that to be terminated.</p> <p>Environment.Exit Method <a title="http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx" href="http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx">http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx</a></p> <p>Process.CloseMainWindow Method <a title="http://msdn.microsoft.com/en-us/library/system.diagnostics.process.closemainwindow.aspx" href="http://msdn.microsoft.com/en-us/library/system.diagnostics.process.closemainwindow.aspx">http://msdn.microsoft.com/en-us/library/system.diagnostics.process.closemainwindow.aspx</a></p> Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-17550174453017179092008-11-17T23:55:00.001-08:002008-11-18T00:02:11.072-08:00Tricks for repairing Visual Studio if it doesn't work with unit test<p>Sometimes, Visual Studio doesn't work with unit test. Unit test list can't be loaded when you try to load an old unit test project. Or, it can load the list, but when you try to run the unit test case, Visual Studio just tell you it is not able to run the unit test, blah blah blah...</p> <p>There must be bugs in Visual Studio or in your unit project settings. Please try the following, the easiest one first:</p> <ol> <li>Delete .suo, .vsmdi of your solution then reload your project.</li> <li>Type <font color="#ff8040"><u>devenv /setup</u></font> or <u><font color="#ff8040">devenv /resetuserdata</font></u>. But please be careful, it will clear your user setting data and Visual Studio will start from a factory state.</li> <li>Check if any references of your unit test project does not work. Just click on the reference, if Visual Studio will bring you to the correct position of the Object Browser, it's the correct reference. Otherwise, not. To fix the reference, first remove the reference, then add it again. If you can't find the reference, probably you have to reinstall the relevant software. The issue I met is TeamSystem.Data.UnitTesting won't work. And the attribute TestMethod is undefined because it is defined in the assembly that hasn't been referenced correctly from the unit test project.</li> </ol> Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com0tag:blogger.com,1999:blog-5512075233013839753.post-87373194940538372312008-10-27T01:22:00.001-07:002008-10-27T01:40:22.407-07:00Tricks for Writing Unit Tests for WPF ApplicationsUsually you write unit tests for non-UI related classes that only do background logics. But sometimes you can't avoid writing unit tests for UI related classes. These days I tried such kind of unit test. And there are some tricks that are useful while you are writing WPF unit tests I willing to share with you. Let's get started. <h3>Get Your Window Ran</h3> First thing first, you should get your window shown and ran. If your window is a child window of your whole application, then you have to create a fake parent window. And then build relationship between the testee window and the fake parent window. <pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-size: 12px; width: 100%; color: rgb(0, 0, 0); line-height: 14px; font-family: andale mono,lucida console,monaco,fixed,monospace; background-color: rgb(238, 238, 238);"><code>Window fakeParentWindow = new Window();<br />Foo testee = new Foo();<br />fakeParentWindow.Content = testee; // if testee is a kind of UIElement<br />testee.Owner = fakeParentWindow; // if testee is a kind of Window<br />fakeParentWindow.Show();<br />testee.Show(); // if it's a Window<br /></code></pre><br />If the testee is a Window, you can let it be the child window of the fakeParentWindow by assign fakeParentWindow to testee's property Owner. Or just do nothing you will get a top window testee. Don't forget to call Show() if it is a Window.<br /><br />That's not everything of initializing a stage for your unit test. There are at least two threads you may interested in<br /><ul><li>Main thread<br /></li><li>The worker thread running as an agent for your unit test case (I don't know why it is called an agent thread)<br /></li></ul>As listed above, your test case will be running within a worker thread. Almost all thread time are dedicated to your test method if you don't carry out some special actions. If your test method blocks the worker thread, your windows won't get message pumped and events won't be handled, and windows even won't get rendered. To solve the problem, just call System.Windows.Threading.Dispatcher.Run() which will start pumping messages and get dispatcher works.<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-size: 12px; width: 100%; color: rgb(0, 0, 0); line-height: 14px; font-family: andale mono,lucida console,monaco,fixed,monospace; background-color: rgb(238, 238, 238);"><code>Dispatcher.CurrentDispatcher.BeginInvoke(<br />DispatcherPriority.Background,<br />new DispatcherOperationCallback(CarryOutTestSteps),<br />null);<br /><br />System.Windows.Threading.Dispatcher.Run();<br /><br /></code></pre>Since Dispatcher.Run() will block the test method, you have to invoke your test steps via CurrentDispatcher.BeginInvoke() in order to starting test. Your test steps will still be processed in the worker thread, but it will be processed as a dispatcher work item.<br /><br />By now, your window is showing.<br /><br />Don't put Dispatcher.Run() into TestInitialize(), because Dispatcher.Run() will also blocks the thread and your test method won't get the chance to run.<br /><h3>Quit the Unit Test</h3>Soon you will find that the unit test won't quit even the dispatcher work item has been completed, and even you close the windows manually. The thread is still enjoying pumping messages. To tell it to stop doing stupid things, just call Dispatcher.ExitAllFrames() when you finished all test steps:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-size: 12px; width: 100%; color: rgb(0, 0, 0); line-height: 14px; font-family: andale mono,lucida console,monaco,fixed,monospace; background-color: rgb(238, 238, 238);"><code>System.Windows.Threading.Dispatcher.ExitAllFrames();<br /></code></pre>Everything looks good, but... you will get an exception during the thread's termination. The exception says:<br /><blockquote><p>"An unhandled exception of type 'System.Runtime.InteropServices.InvalidComObjectException' occurred in PresentationCore.dll Additional information: COM object that has been separated from its underlying RCW cannot be used."<br /></p></blockquote>I searched on the Internet. Eventually I found that was a bug of .Net Framework. A work around came from Visual Studio Product Team is calling CurrentDispatcher.InvokeShutdown() from TestCleanup().<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-size: 12px; width: 100%; color: rgb(0, 0, 0); line-height: 14px; font-family: andale mono,lucida console,monaco,fixed,monospace; background-color: rgb(238, 238, 238);"><code>[TestCleanup]<br />public void TestCleanup()<br />{<br />System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown();<br />}<br /></code></pre>Be careful, .Net Framework may be changed letting this work around unnecessary.<br /><h3>References<br /></h3><ol><li><a href="http://codegator.com/mcook/archive/2008/04/25/wpf-visual-studio-2008-unit-test-workaround.aspx" target="_blank">WPF / Visual Studio 2008 Unit Test Workaround</a><br /></li><li><a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=318333" target="_blank">Unit Tests Which Show Windows Cause VsTestHost/MsTest ShutDown Crashes in VS 2008 RTM</a><br /></li></ol>Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com2tag:blogger.com,1999:blog-5512075233013839753.post-8053078976740193982008-10-16T02:22:00.001-07:002008-10-16T19:29:47.004-07:00WPF Threading Model via Windbg<p>In this post, I will show you how to discover the threading model of WPF via Windbg. This post is not a complete description of WPF threading model, but just listed what I've found after my efforts.</p> <p>Windbg is a powerful debugger, though may be not the most powerful one. It can really help you to find root causes for some though bugs. <a href="http://windbg.dumpanalysis.org/" target="_blank">Download Windbg here</a>.</p> <p>To dive into WPF, first, create a simple WPF application. Just use Visual Studio to create a default WPF application project. And build the application to get executable generated. Then, launch Windbg, and load it into Windbg. Don't forget to load Windbg extensions such as sos or psscor2, to help your debugging.</p> <p>OK, let the application run. When you see the application window, break the application by clicking the 'break' button on the Windbg's toolbar. Let's go to thread 0 and see its stack by these two commands:</p> <pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>~0s<br />!clrstack<br /></code></pre><br />The first command switches current thread to 0, and the second will display CLR stack. It's very clear that thread 0 is our UI thread. <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>0030e824 56d5dfe0 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)<br />0030ec5c 00a20bd3 [InlinedCallFrame: 0030ec5c] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)<br />0030ec58 56d5f0fe MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr)<br />0030ede8 00a20bd3 [NDirectMethodFrameStandalone: 0030ede8] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)<br />0030ee04 56d5dfe0 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)<br />0030ef90 00a20bd3 [NDirectMethodFrameStandalone: 0030ef90] MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)<br />0030efa0 56d61824 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)<br />0030eff0 56d616c7 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)<br />0030f00c 56d6162d System.Windows.Threading.Dispatcher.Run()<br />0030f018 5533ddb0 System.Windows.Application.RunInternal(System.Windows.Window)<br />0030f044 5533dbe5 System.Windows.Application.Run(System.Windows.Window)<br />0030f054 5533d836 System.Windows.Application.Run()<br />0030f05c 003500ad SimpleWPFApp.App.Main()<br />0030f284 79e7c74b [GCFrame: 0030f284] <br /></code></pre><br />You may want to try other threads, and will find they are not CLR threads. And next step, let's try to find which thread is render thread. Use command 'kb' repeatedly and you will find one thread looks interesting. It is trying to GetWork and is waiting for something. <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>0:005> kb<br />ChildEBP RetAddr Args to Child <br />0491fab0 77719254 7679c244 00000234 00000000 ntdll!KiFastSystemCallRet [d:\rtm\base\ntos\rtl\i386\userdisp.asm @ 645]<br />0491fab4 7679c244 00000234 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc [o:\rtm.obj.x86fre\base\ntdll\daytona\objfre\i386\usrstubs.asm @ 2939]<br />0491fb24 7679c1b2 00000234 ffffffff 00000000 KERNEL32!WaitForSingleObjectEx+0xbe [d:\rtm\base\win32\client\synch.c @ 1524]<br />0491fb38 72790b19 00000234 ffffffff 004dd410 KERNEL32!WaitForSingleObject+0x12 [d:\rtm\base\win32\client\synch.c @ 1429]<br />0491fb68 7278aadc 0491fb7c 004dd410 004dd4a0 MilCore!CPartitionManager::GetWork+0x1a5 [d:\rtm\windows\mil\core\uce\partitionmanager.cpp @ 1111]<br />0491fb80 7278aaa4 00000000 00000000 004dd410 MilCore!CPartitionThread::Run+0x1a [d:\rtm\windows\mil\core\uce\partitionthread.cpp @ 222]<br />0491fb98 76794911 004dd410 0491fbe4 776fe4b6 MilCore!CPartitionThread::ThreadMain+0x1e [d:\rtm\windows\mil\core\uce\partitionthread.cpp @ 46]<br />0491fba4 776fe4b6 004dd410 73edafdb 00000000 KERNEL32!BaseThreadInitThunk+0xe [d:\rtm\base\win32\client\thread.c @ 66]<br />0491fbe4 776fe489 7278aa86 004dd410 00000000 ntdll!__RtlUserThreadStart+0x23 [d:\rtm\base\ntos\rtl\rtlexec.c @ 2740]<br />0491fbfc 00000000 7278aa86 004dd410 00000000 ntdll!_RtlUserThreadStart+0x1b [d:\rtm\base\ntos\rtl\rtlexec.c @ 2672]<br /></code></pre><br />By checking the call stack, we find there's an argument passed to WaitForSingleObject and WaitForSingleObjectEx. The argument is 00000234. It looks like some synchronization objects. Let's check what is it: <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>0:000> !handle 0x234 ff<br />Handle 234<br /> Type Event<br /> Attributes 0<br /> GrantedAccess 0x1f0003:<br /> Delete,ReadControl,WriteDac,WriteOwner,Synch<br /> QueryState,ModifyState<br /> HandleCount 2<br /> PointerCount 4<br /> Name <none><br /> Object Specific Information<br /> Event Type Auto Reset<br /> Event is Waiting<br /></code></pre><br />Windbg tells us it's an event handle. Hmmm, that's reasonable. If you continue to check other thread's call stack, and you will find there's only one thread is waiting for some synchronization events. This thread must be render thread, because communication between render thread and UI thread must be based on synchronization object. So, next task is to find where the event been set. Set breakpoint on KERNEL32!SetEvent won't work for us because there are so many calls to SetEvent everywhere in the application. Windbg offers a kind of conditional breakpoint which can help us to break the application at the right position. <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>bp kernel32!SetEvent "j (edx=234) '.echo foo';'gc'"<br /></code></pre><br />Here 234 is the event handle, remember that we found this handle in render thread. You should replace it with the handle you find in your situation. Let the application go. The breakpoint is so great though, it seems that it can't be hit every time when the code goes to the right position. I don't know why. But if you try to resize the application's window repeatedly, you will have greater chance to hit the breakpoint. When the application got hit the breakpoint, you can see the call stack of thread 0 like this: <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>0:000> kb<br />ChildEBP RetAddr Args to Child <br />0030d95c 72748a36 00000234 004de51c 004b3a18 KERNEL32!SetEvent+0x14 [d:\rtm\base\win32\client\synch.c @ 506]<br />0030d978 727489d1 004b3a18 004de2f0 00000000 MilCore!CPartitionManager::ScheduleBatchProcessing+0x54 [d:\rtm\windows\mil\core\uce\partitionmanager.cpp @ 482]<br />0030d9d0 7274974e 0030d9ec 0030da24 004e7188 MilCore!CComposition::SubmitBatch+0x96 [d:\rtm\windows\mil\core\uce\composition.cpp @ 359]<br />0030d9e4 727488ba 004b3a18 0030da34 004de1d0 MilCore!CConnectionContext::SendBatchToChannel+0x30 [d:\rtm\windows\mil\core\uce\connectioncontext.cpp @ 568]<br />0030d9f8 72748868 00000004 004e7294 0030da3c MilCore!CConnectionContext::SendPacketToConnection+0xee [d:\rtm\windows\mil\core\uce\connectioncontext.cpp @ 450]<br />0030da08 727491cd 0030da24 01d47b28 00000003 MilCore!CMilCrossThreadTransport::PostPacket+0x3b [d:\rtm\windows\mil\core\uce\crossthreadtransport.cpp @ 145]<br />0030da3c 727491ff 004e7294 004e7208 72742c35 MilCore!CMilConnection::SubmitBatch+0xa9 [d:\rtm\windows\mil\core\uce\connection.cpp @ 619]<br />0030da48 72742c35 01d47b28 72742c9f 004e7208 MilCore!CMilChannel::FlushCommands+0x21 [d:\rtm\windows\mil\core\uce\clientchannel.cpp @ 721]<br />0030da50 72742c9f 004e7208 0030daa0 5395bc2d MilCore!CMilChannel::Commit+0x20 [d:\rtm\windows\mil\core\uce\clientchannel.cpp @ 626]<br />0030da5c 5395bc2d 004e7208 a1590ca7 79e73940 MilCore!MilChannel_CommitChannel+0x21 [d:\rtm\windows\mil\core\uce\apifunc.cpp @ 523]<br />0030daa0 539bb1b3 0000004f 00000003 00000000 PresentationCore_ni!`dynamic atexit destructor for '<CrtImplementationDetails>::AtExitLock::_lock'' <PERF> (PresentationCore_ni+0xbbc2d)<br />0030db10 53977fea 00000000 0000020f 0000024e PresentationCore_ni!`dynamic atexit destructor for '<CrtImplementationDetails>::AtExitLock::_lock'' <PERF> (PresentationCore_ni+0x11b1b3)<br />0030db98 79e75519 56d61428 00000000 01d116b0 PresentationCore_ni!`dynamic atexit destructor for '<CrtImplementationDetails>::AtExitLock::_lock'' <PERF> (PresentationCore_ni+0xd7fea)<br />0030db9c 56d61428 00000000 01d116b0 01d6c134 mscorwks!ThreadNative::FastGetCurrentThread+0x6 [f:\redbits\ndp\clr\src\vm\comsynchronizable.cpp @ 1004]<br />00000000 00000000 00000000 00000000 00000000 WindowsBase_ni!IsEncryptedPackageEnvelope+0x53 [d:\SP1\windows\wcp\Base\System\IO\Packaging\EncryptedPackage.cs @ 595]<br /></code></pre><br />It's interesting. Isn't it? Check the handle 234 right now and you will see the event is still in waiting state. But if you step over KERNEL32!SetEvent, you will find the event turned to 'set state': <br /><br /><pre style="border-right: #999999 1px dashed; padding-right: 5px; border-top: #999999 1px dashed; padding-left: 5px; font-size: 12px; padding-bottom: 5px; overflow: auto; border-left: #999999 1px dashed; width: 100%; color: #000000; line-height: 14px; padding-top: 5px; border-bottom: #999999 1px dashed; font-family: andale mono, lucida console, monaco, fixed, monospace; background-color: #eee"><code>0:000> !handle 0x234 ff<br />Handle 234<br /> Type Event<br /> Attributes 0<br /> GrantedAccess 0x1f0003:<br /> Delete,ReadControl,WriteDac,WriteOwner,Synch<br /> QueryState,ModifyState<br /> HandleCount 2<br /> PointerCount 4<br /> Name <none><br /> Object Specific Information<br /> Event Type Auto Reset<br /> Event is Set<br /></code></pre><br />From current UI thread's call stack you can find the data submission and synchronization secrete. UI thread and render thread are working in an asynchronous mode. It means that even if you completed some invocations of drawing objects, these drawing commands may be pending in the queue and won't be executed by render thread. I remember that once I am developing a program that drawing some animation, I found that even if I received the animation completion event, the animation was still going on on the screen. Anonymoushttp://www.blogger.com/profile/17168341871311932907noreply@blogger.com105