using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
using System.Threading;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel; namespace IronPythonDebugger
{
public class IronPythonDebugger : IIronPythonDebugger
{
private ScriptEngine _engine; private ScriptScope _scope; private string _source; private string _debugSource; private ScriptSource _debugScriptSource; private Dictionary<int, bool> _breakpoints; private Thread _debugThread; private int _currentLine = ;//从1开始计算 private int _logicStartLine;//从1开始计算 private ScriptBackgroundExecute _backgroundExecute; private bool _debugging = false; private int _sourceLineCount; private const string BACKGROUND_BREAK_CODE = "_backgroundExecute.Break()"; private Action<int> _breakCallback; private int _nextBreakLine; private bool _debugThreadSleep = false; private AsyncOperation _asyncOp; private Action _exec; private SendOrPostCallback _onBreakCallback; private void Execute()
{
try
{
_debugScriptSource.Execute(_scope);
}
catch (DebugStopException)
{
}
catch (ThreadAbortException)
{
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
Stop();
}
} private void BackgroundBreakCallback()
{
if (!_debugging)
{
throw new DebugStopException();
}
_currentLine++;
if (_currentLine == _nextBreakLine)
{
_debugThreadSleep = true;
//if (_breakCallback != null)
//{
// _breakCallback(_currentLine);
//}
_asyncOp.Post(_onBreakCallback, _currentLine);
WaitDebugThreadContinue();
}
} private void OnBreakCallback(object lineNumber)
{
if (Break != null)
{
Break(this, new BreakEventArgs((int)lineNumber));
}
else if (_breakCallback != null)
{
_breakCallback((int)lineNumber);
}
} private void WaitDebugThreadContinue()
{
while (_debugThreadSleep)
{
Thread.Sleep();
}
} private void AddBackgroundBreakCode()
{
string[] lines = _source.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
_sourceLineCount = lines.Length;
_logicStartLine = GetLogicStartLine(lines);//获取第一行逻辑代码的行号
_debugSource = string.Empty;
for (int i = ; i < _sourceLineCount; i++)
{
if (!string.IsNullOrEmpty(_debugSource))
{
_debugSource += Environment.NewLine;
}
if (i >= _logicStartLine - )
{
_debugSource += BACKGROUND_BREAK_CODE + Environment.NewLine;
}
_debugSource += lines[i];
}
} ////import clr,sys
////clr.AddReference('TestClass')
////clr.AddReference('System.Windows.Forms')
////from TestClass import *
////from System.Windows.Forms import * ////c1 = Class1()
////c1.Name = "c1"
////MessageBox.Show(c1.Name)
////child = Class1()
////child.Name = "child1"
////c1.Child = child
////MessageBox.Show(c1.Child.Name)
private int GetLogicStartLine(string[] lines)
{
int startLine = ;
for (int i = ; i < lines.Length;i++ )
{
string line = lines[i].ToLower();
if (line.IndexOf("import") <
&& line.IndexOf("clr") <
&& line.IndexOf("from") < )
{
startLine = i + ;
break;
}
}
return startLine;
} private int GetNextBreakLine(int currentLine)
{
int next = -;
_breakpoints.OrderBy(breakpoint => breakpoint.Key);
foreach (KeyValuePair<int, bool> breakpoint in _breakpoints)
{
if (breakpoint.Value && breakpoint.Key > currentLine)
{
next = breakpoint.Key;
break;
}
}
return next;
} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public event Action<object, BreakEventArgs> Break; public ScriptEngine Engine
{
get
{
return _engine;
}
} public ScriptScope Scope
{
get
{
return _scope;
}
} public string Source
{
get
{
return _source;
}
} public Action<int> BreakCallback
{
get
{
return _breakCallback;
} set
{
_breakCallback = value;
}
} public IronPythonDebugger()
{
_engine = Python.CreateEngine();
_scope = _engine.CreateScope();
_scope.SetVariable("_backgroundExecute", _backgroundExecute);
_breakpoints = new Dictionary<int, bool>();
_backgroundExecute = new ScriptBackgroundExecute(BackgroundBreakCallback);
_exec = new Action(Execute);
_onBreakCallback = new SendOrPostCallback(OnBreakCallback);
} public void InitialDebugger()
{
if (_debugging)
{
throw new Exception("调试器正在调试中!");
}
_scope = _engine.CreateScope();
_scope.SetVariable("_backgroundExecute", _backgroundExecute);
_breakpoints.Clear();
} public void InitialDebugger(List<int> breakpoints)
{
InitialDebugger();
foreach (int breakpoint in breakpoints)
{
_breakpoints[breakpoint] = true;
}
} public void ClearBreakpoints()
{
_breakpoints.Clear();
} public void Start(string source)
{
if (_debugging)
{
throw new Exception("调试器正在调试中!");
}
_source = source;
AddBackgroundBreakCode();
_debugScriptSource = _engine.CreateScriptSourceFromString(_debugSource);
_currentLine = _logicStartLine - ;
_debugThreadSleep = false;
_nextBreakLine = GetNextBreakLine();
//_debugThread = new Thread(Execute);
//_debugThread.Start();
_asyncOp = AsyncOperationManager.CreateOperation();
_exec.BeginInvoke(null, null);
_debugging = true;
} public void Stop()
{
if (_debugging)
{
_debugging = false;
_debugThreadSleep = false;
//if (_debugThread != null && _debugThread.IsAlive)
//{
// _debugThread.Abort();
//}
}
} public void AddBreakpoint(int line)
{
_breakpoints[line] = true;
} public void AddBreakpoints(List<int> lines)
{
foreach (int line in lines)
{
AddBreakpoint(line);
}
} public void DeleteBreakpoint(int line)
{
_breakpoints[line] = false;
} public void DeleteBreakpoints(List<int> lines)
{
foreach (int line in lines)
{
DeleteBreakpoint(line);
}
} public void StepOver()
{
if (!_debugging)
{
throw new Exception("调试器未开始调试!");
}
_nextBreakLine++;
_debugThreadSleep = false;
} public void StepInto()
{
MessageBox.Show("暂不支持逐语句调试!");
} public void StepOut()
{
MessageBox.Show("暂不支持跳出调试!");
} public void Continue()
{
if (!_debugging)
{
throw new Exception("调试器未开始调试!");
}
_nextBreakLine = GetNextBreakLine(_currentLine);
_debugThreadSleep = false;
} public string GetValueAsString(string variable)
{
string value = string.Empty;
try
{
string[] names = variable.Split('.');
object obj = _scope.GetVariable(names[]);
for (int i = ; i < names.Length; i++)
{
Type type = obj.GetType();
PropertyInfo pi = type.GetProperty(names[i]);
obj = pi.GetValue(obj, null);
}
value = obj.ToString();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return value;
} public bool IsDebugging()
{
return _debugging;
}
} public class BreakEventArgs : EventArgs
{
public int LineNumber; public BreakEventArgs(int lineNumber)
{
this.LineNumber = lineNumber;
}
} public class DebugStopException : Exception
{
}
}

异步编程设计模式 - IronPythonDebugger的更多相关文章

  1. 异步编程设计模式Demo - AsyncComponentSample

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...

  2. 异步编程设计模式Demo - PrimeNumberCalculator

    using System; using System.Collections; using System.Collections.Specialized; using System.Component ...

  3. [.net 多线程]异步编程模式

    .NET中的异步编程 - EAP/APM 从.NET 4.5开始,支持的三种异步编程模式: 基于事件的异步编程设计模式 (EAP,Event-based Asynchronous Pattern) 异 ...

  4. JavaScript异步编程的主要解决方案—对不起,我和你不在同一个频率上

    众所周知(这也忒夸张了吧?),Javascript通过事件驱动机制,在单线程模型下,以异步的形式来实现非阻塞的IO操作.这种模式使得JavaScript在处理事务时非常高效,但这带来了很多问题,比如异 ...

  5. C#基础系列——异步编程初探:async和await

    前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了 ...

  6. C#编程总结(六)异步编程

    C#编程总结(六)异步编程 1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某 ...

  7. node.js整理 06异步编程

    回调 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了 function heavyCompute(n, callback) { var count = 0, i, j; for (i = ...

  8. 你所必须掌握的三种异步编程方法callbacks,listeners,promise

    目录: 前言 Callbacks Listeners Promise 前言 coder都知道,javascript语言运行环境是单线程的,这意味着任何两行代码都不能同时运行.多任务同时进行时,实质上形 ...

  9. NodeJS学习之异步编程

    NodeJS -- 异步编程 NodeJS最大的卖点--事件机制和异步IO,对开发者并不透明 代码设计模式 异步编程有很多特有的代码设计模式,为了实现同样的功能,使用同步方式和异步方式编写代码会有很大 ...

随机推荐

  1. 字符串时间日期转为Date格式和long格式

    public static Long compare_date(String DATE1, String DATE2) { DateFormat df = new SimpleDateFormat(& ...

  2. iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比

    iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比   iphoneiPhoneIPhoneIPHONEIphone数据持久化 对比总结 本篇对IOS中常用的5种数据持久化方法进行简单 ...

  3. PHP 之mysql空字符串问题

    有一张user表如下所示:字段name不能为空. CREATE TABLE `user` ( `id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, `a ...

  4. 通过JCONSOLE监控TOMCAT的JVM使用情况

    这个也是要学入一下,JVMr 虚拟机原理不可少. 参考配置URL“: http://blog.163.com/kangle0925@126/blog/static/277581982011527723 ...

  5. STL中序列式容器的共性

    代码如下: /* * vector_1.cpp * * Created on: 2013年8月6日 * Author: Administrator */ #include <iostream&g ...

  6. poj 2100 Graveyard Design(尺取法)

    Description King George has recently decided that he would like to have a new design for the royal g ...

  7. 响应式布局:Flexbox应用总结

    距离上篇文章<布局神器:Flexbox>的发表已有一周时间,转眼这周又到了周五(O(∩_∩)O~~): 习惯性在周五对自己的一周工作进行下总结,记录下这周值得被纪念的工作事件,无论是好的, ...

  8. 未能载入文件或程序集“DAL”或它的某一个依赖项。系统找不到指定的文件。

    这个一般出如今三层给B层与D层之间加抽象工厂-接口-映射.时候出的错.出错的地方是抽象工厂. --如图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTA ...

  9. [小技巧] 把虚拟机中的Linux系统安装到U盘中

    出于各种需求,很多用户可能经常会在Windows系统中安装虚拟机,然后在虚拟机中安装Linux系统.使用虚拟机的优点是可以同时使用多个系统,而缺点也是显然的,也就是程序运行效率较差.   而实际上,L ...

  10. JavaScript函数 bind call apply区别

    1. apply calll 在JavaScript中 call 和 apply 都是为了改变某个函数运行时上下文而存在的, 换句话说就是为了改变函数内部的this的指向. 这里我们有一个新的对象 b ...