以下内容是在newsgroups中解决一个朋友的问题而写的demo, 留下给自己做个备忘录.

----

关于PageAsyncTask在MSDN上的参考
ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_system.web/html/08ffac7a-2c3c-27ee-1445-5284a226be38.htm

说明: 此页面中, 在Page_Load方法中, 同时启动4个较耗时的任务(线程), 让它们并行的运行, 然后等待他们都运行完毕或超时.

using System;
using System.Diagnostics;
using System.Threading;
using System.Web.Mvc;
using System.Web.UI;
 
namespace Portal.Views.Home
{
    public partial class Index : ViewPage
    {
        private string _asyncResult;
        private AsyncTaskDelegate _asyncTask;
 
        protected void Page_Load(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
 
            PageAsyncTask task1 =
                new PageAsyncTask(OnTaskBegin, OnTaskEnd, OnTaskTimeout, "A1", true);
            PageAsyncTask task2 =
                new PageAsyncTask(OnTaskBegin, OnTaskEnd, OnTaskTimeout, "B2", true);
            PageAsyncTask task3 =
                new PageAsyncTask(OnTaskBegin, OnTaskEnd, OnTaskTimeout, "C3", true);
            PageAsyncTask task4 =
                new PageAsyncTask(OnTaskBegin, OnTaskEnd, OnTaskTimeout, "D4", true);
 
            RegisterAsyncTask(task1);
            RegisterAsyncTask(task2);
            RegisterAsyncTask(task3);
            RegisterAsyncTask(task4);
 
            // By default, an asynchronous task will time out if it has not completed
            // within 45 seconds.
            AsyncTimeout = TimeSpan.FromSeconds(60);
 
            ExecuteRegisteredAsyncTasks();
 
            sw.Stop();
 
            // now, we can get the task result here.
            Response.Write(_asyncResult);
            Response.Write(sw.Elapsed.TotalSeconds);
        }
 
        private IAsyncResult OnTaskBegin(object sender,
                                         EventArgs e,
                                         AsyncCallback callback,
                                         object data)
        {
            _asyncTask = delegate(string text)
            {
                // TODO: add your async task here.
                string response =
                    string.Format("AsyncTask {0} started at: {1}. ", text, DateTime.Now);
                Thread.Sleep(TimeSpan.FromSeconds(10));
                response +=
                    string.Format("AsyncTask {0} ended at: {1}.\n", text, DateTime.Now);
                return response;
            };
 
            IAsyncResult result = _asyncTask.BeginInvoke((string) data, callback, data);
            return result;
        }
 
        private void OnTaskEnd(IAsyncResult ar)
        {
            _asyncResult += _asyncTask.EndInvoke(ar);
        }
 
        private void OnTaskTimeout(IAsyncResult ar)
        {
            _asyncResult = string.Format("AsyncTask {0} is time out.", ar.AsyncState);
        }
 
        #region Nested type: AsyncTaskDelegate
 
        protected delegate string AsyncTaskDelegate(string text);
 
        #endregion
    }
}

reference: http://msdn.microsoft.com/en-us/library/system.web.ui.pageasynctask(zh-cn).aspx
posted @ 2008-04-27 01:56 rex xiang 阅读(65) | 评论 (1)编辑

    关于调试windows service, 其实这是一个老生常谈的问题了.

    通常的处理办法是, 在service运行后, 在调试器中选择attach to process.

    然而这种做法也有一定的局限性, 例如在service启动时的OnStart事件中的代码, 基本上很难调试. 往往当attach到我们的service的时候, 这部分代码已经执行过了. 于是, 有人提出, 可以另写一个project来调用这个OnStart方法, 或将OnStart方法中的代码搬到另一个project中测试. 不过, 这些方法终究不是以windows服务的方式调试的, 不能够最真实的反应service运行时的执行状况(如权限问题等环境问题).

    我的做法是, 在OnStart方法的最开始部分加上"Debugger.Launch()"的调用, 当service运行到此处时, 将会弹出一个选择调试器的对话框, 同时暂停在当前位置. 这样, 我们就做到了在代码中手动的启动调试器.

    示例代码如下:

using System.Diagnostics;
 
public partial class MyService : ServiceBase{
    public MyService(){
        InitializeComponent();
    } 
 
    protected override void OnStart(string[] args){
#if DEBUG
        Debugger.Launch();    //Launches and attaches a debugger to the process.
#endif
        // TODO: add your initialize code here.
    } 
 
    protected override void OnStop(){
    }
}

posted @ 2008-03-30 04:02 rex xiang 阅读(218) | 评论 (1)编辑

今天一位同事遇到JS上的郁闷事情, 现象描述: 在ASPX页面中, 给某个hidden控件赋值后, 在后台CS文件中取到的值与之不符. (也就是说,总会被某个操作悄悄的改变这个hidden的值,此ASPX页面运行在某个OA系统的JS框架下). 为了找出罪魁祸首, 我写了一段测试代码, 来检测当某个控件属性被修改时, 找出是哪个函数在做手脚.

<html>
    <head>
        <script type="text/jscript">
        function controlPropertyChanged(){
            var name =  event.propertyName;
            if(name != 'value'){
                return;
            }
            
            var caller = controlPropertyChanged.caller;
            var callerText = "";
            
            while(caller != null){
                callerText += "\n--------\n" + caller.toString();
                caller = caller.caller;
            }
 
            var value = event.srcElement.value;
            alert("value = " + value + callerText);
        }
        </script>
 
    </head>
    <body>
        <form action="">
        <input id="ctlAHidden" type="hidden" value="" onpropertychange="controlPropertyChanged();" />
        
        <input type="button" value="change value 1" onclick="document.all('ctlAHidden').value = 'new value 1';" />
        <input type="button" value="change value 2" onclick="document.all('ctlAHidden').value = 'new value 2';" />
        </form>
    </body>
</html>
posted @ 2008-03-18 14:59 rex xiang 阅读(41) | 评论 (2)编辑

前段时间,大概用了一下LINQ to SQL, 发觉O/Rdesigner似乎没有Many-To-Many(多对多)关系的支持,只有自己写代码实现.
:(

提供一下俺的解决办法:
例如User和UserGroup的关系,假设保存在UserInGroups表中,这里记录了User和Group的对应关系,那么,需要手动在User/Group类中添加对应的partial属性:

public partial class User{ 
    piblic IEnumerable<Groups> Groups 
    { 
        var groups = from g in db.UserInGroups 
                            where g.UserId = this.UserId 
                            select {g.Groups}; 
        return groups; 
    } 
}
 
 
public partial class Group{ 
    piblic IEnumerable<Users> Users 
    { 
        var users = from u in db.UserInGroups 
                            where u.GroupId = this.GroupId 
                            select {u.Users}; 
        return users; 
    } 
}
posted @ 2007-12-27 18:44 rex xiang 阅读(99) | 评论 (0)编辑

  什么是custom tool? 对visual studio比较熟悉的人, 可能都曾经注意到过, 自从VS2002开始, solution explorer中文件的properties中, 都有一个Custom Tool属性.

  例如, 我们在VS中通过菜单Project -> Add New Item -> Data -> DataSet创建一个DataSet1.xsd文件, 此时, 我们发现DataSet1.xsd文件的properties中的custom tool属性为MSDataSetGenerator.

  当我们更改DataSet1.xsd文件时, 仔细观察, 我们发现与之相对应的DataSet1.Designer.cs文件中也会生成做出相应的更新.
如果我们删除此文件, 再次保存DataSet1.xsd, 将看到DataSet1.Designer.cs又出现了.
然后, 我们再次删除DataSet1.Designer.cs文件, 去掉DataSet1.xsd文件properties中的Custom Tool属性, 再次保存, DataSet1.Designer.cs却没有出现了.

image

同样, 具有Custom Tool属性的*dbml文件也有相同的特性.

image

于是, 我们有理由相信*.Designer.cs文件的出现, 和对应文件的Custom Tool属性有莫大的关系.

  实际上, Custom Tool属性的作用是, 当具有此属性的文件在保存时, 将调用指定的接口来处理此文件. 例如, 根据DataSet1.xsd文件生成相应的DataSet1.Designer.cs文件. 另一个常见的例子是: 根据wsdl生成WebService代理类.

  或许, 如果我们合理的利用此接口, 可为我们的工作剩下不少的时间.

 

以下是MSDN关于此接口的资料.

Implementing Single File Generators:
http://msdn2.microsoft.com/en-us/library/s686w8yb(VS.80).aspx

    A custom tool — sometimes referred to as a single file generator — can be used to extend the Visual Basic, Visual C#, and Visual J# project systems in Visual Studio. A custom tool is a COM component that implements the IVsSingleFileGenerator interface. Using this interface, a custom tool transforms a single input file into a single output file. The result of the transformation may be source code, or any other output that is useful. Two examples of custom tool-generated code files are code generated in response to changes in a visual designer and files generated using Web Services Description Language (WSDL).

    When a custom tool is loaded, or the input file is saved, the project system calls the Generate method, and passes a reference to a IVsGeneratorProgress callback interface, whereby the tool can report its progress to the user.

    The output file that the custom tool generates is added to the project with a dependency on the input file. The project system automatically determines the name of the output file, based on the string returned by the custom tool's implementation of DefaultExtension.

    A custom tool must implement the IVsSingleFileGenerator interface. Optionally, custom tools support the IObjectWithSite interface to retrieve information from sources other than the input file. In any case, before you can use a custom tool, you must register it with the system or in the Visual Studio local registry. For more information on registering custom tools, see Registering Single File Generators.

 

Assembly: Microsoft.VisualStudio.Shell.Interop (in microsoft.visualstudio.shell.interop.dll)

posted @ 2007-10-29 16:13 rex xiang 阅读(42) | 评论 (0)编辑